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
¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
cyclomatic | McCabe's cyclomatic complexity TYPE: |
cognitive | Cognitive complexity (how hard to understand) TYPE: |
halstead_volume | Halstead volume metric TYPE: |
halstead_difficulty | Halstead difficulty metric TYPE: |
halstead_effort | Halstead effort metric TYPE: |
maintainability_index | Maintainability index (0-100) TYPE: |
nesting_depth | Maximum nesting depth TYPE: |
parameter_count | Number of parameters (for functions) TYPE: |
line_count | Number of lines TYPE: |
token_count | Number of tokens TYPE: |
operator_count | Number of unique operators TYPE: |
operand_count | Number of unique operands TYPE: |
Attributes¶
complexity_per_lineproperty
¶
Calculate complexity per line of code.
RETURNS | DESCRIPTION |
---|---|
float | Cyclomatic complexity divided by lines TYPE: |
FunctionComplexitydataclass
¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
name | Function name TYPE: |
full_name | Fully qualified name (with class if method) TYPE: |
file_path | Path to containing file TYPE: |
line_start | Starting line number TYPE: |
line_end | Ending line number TYPE: |
metrics | Detailed complexity metrics TYPE: |
calls | Functions called by this function |
called_by | Functions that call this function |
is_recursive | Whether function is recursive TYPE: |
is_generator | Whether function is a generator TYPE: |
is_async | Whether function is async TYPE: |
has_decorator | Whether function has decorators TYPE: |
docstring | Function docstring if present |
ClassComplexitydataclass
¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
name | Class name TYPE: |
file_path | Path to containing file TYPE: |
line_start | Starting line number TYPE: |
line_end | Ending line number TYPE: |
metrics | Aggregated complexity metrics TYPE: |
methods | List of method complexity analyses TYPE: |
nested_classes | List of nested class complexities TYPE: |
inheritance_depth | Depth in inheritance hierarchy TYPE: |
parent_classes | List of parent class names |
abstract_methods | Count of abstract methods TYPE: |
static_methods | Count of static methods TYPE: |
properties | Count of properties TYPE: |
instance_attributes | Count of instance attributes TYPE: |
FileComplexitydataclass
¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
path | File path TYPE: |
name | File name TYPE: |
language | Programming language TYPE: |
metrics | File-level complexity metrics TYPE: |
functions | List of function complexities TYPE: |
classes | List of class complexities TYPE: |
total_complexity | Sum of all complexity in file TYPE: |
max_complexity | Maximum complexity found in file TYPE: |
complexity_hotspots | Areas of high complexity |
import_complexity | Complexity from imports/dependencies TYPE: |
coupling | Coupling metric TYPE: |
cohesion | Cohesion metric TYPE: |
ComplexityReportdataclass
¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
total_files | Total files analyzed TYPE: |
total_functions | Total functions analyzed TYPE: |
total_classes | Total classes analyzed TYPE: |
avg_complexity | Average cyclomatic complexity TYPE: |
max_complexity | Maximum cyclomatic complexity found TYPE: |
median_complexity | Median cyclomatic complexity TYPE: |
std_dev_complexity | Standard deviation of complexity TYPE: |
high_complexity_count | Count of high complexity items TYPE: |
very_high_complexity_count | Count of very high complexity items TYPE: |
files | List of file complexity analyses TYPE: |
top_complex_functions | Most complex functions TYPE: |
top_complex_classes | Most complex classes TYPE: |
top_complex_files | Most complex files TYPE: |
complexity_distribution | Distribution of complexity values |
refactoring_candidates | Items recommended for refactoring |
technical_debt_hours | Estimated hours to address complexity TYPE: |
trend_direction | Whether complexity is increasing/decreasing TYPE: |
recommendations | List of actionable recommendations |
Attributes¶
complexity_scoreproperty
¶
Calculate overall complexity score (0-100).
Lower scores indicate better (less complex) code.
RETURNS | DESCRIPTION |
---|---|
float | Complexity score TYPE: |
Functions¶
to_dict¶
Convert report to dictionary.
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Dictionary representation |
Source code in tenets/core/examiner/complexity.py
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¶
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.
ATTRIBUTE | DESCRIPTION |
---|---|
config | Configuration object |
logger | Logger instance |
complexity_cache | Cache of computed complexities |
Initialize complexity analyzer.
PARAMETER | DESCRIPTION |
---|---|
config | TenetsConfig instance TYPE: |
Source code in tenets/core/examiner/complexity.py
Functions¶
analyze¶
Analyze complexity for a list of files.
Performs comprehensive complexity analysis across all provided files, calculating various metrics and identifying problem areas.
PARAMETER | DESCRIPTION |
---|---|
files | List of analyzed file objects |
threshold | Complexity threshold for flagging TYPE: |
deep | Whether to perform deep analysis TYPE: |
RETURNS | DESCRIPTION |
---|---|
ComplexityReport | Comprehensive complexity analysis TYPE: |
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
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¶
Analyze complexity for a single file.
PARAMETER | DESCRIPTION |
---|---|
file_analysis | Analyzed file object TYPE: |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: File complexity details |
Source code in tenets/core/examiner/complexity.py
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¶
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.
PARAMETER | DESCRIPTION |
---|---|
files | List of analyzed file-like objects |
threshold | Threshold for high/very high classification TYPE: |
config | Optional TenetsConfig instance TYPE: |
RETURNS | DESCRIPTION |
---|---|
ComplexityReport | ComplexityReport |
Source code in tenets/core/examiner/complexity.py
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)