A comprehensive static code analysis tool for Xojo 2025 API 2 projects that detects code smells, analyzes complexity, tracks relationships, and generates detailed multi-page PDF reports.
This tool scans Xojo project files (.xojo_project, .xojo_code, .xojo_window, etc.) to provide deep insights into code quality, architecture, and potential issues. It generates professional PDF reports with visualizations, metrics, and actionable recommendations.
Identifies 153+ code quality issues across multiple categories:
- God Classes: Classes with too many responsibilities (>40 methods or >1000 LOC)
- Long Methods: Methods exceeding 50 lines of code
- Deep Nesting: Code with >3 levels of nesting
- Magic Numbers: Hard-coded numeric values without explanation
- Duplicate Code: Similar code patterns across methods
- Large Classes: Classes with excessive size
- Long Parameter Lists: Methods with >5 parameters
- Feature Envy: Methods accessing other classes' data more than their own
- Data Clumps: Same group of parameters appearing together repeatedly
- Primitive Obsession: Overuse of primitive types instead of objects
- Missing Error Handling: File operations, network calls, database queries without Try/Catch
- Bare Catch Blocks: Catch blocks without proper exception handling
- Risky Operations: Type conversions, file operations, network/database calls without protection
- Cyclomatic Complexity: Measures code branching and decision paths
- Lines of Code (LOC): Tracks method and class sizes
- Nesting Depth: Identifies deeply nested control structures
- Parameter Complexity: Analyzes method parameter counts and optional parameters
- Method Call Detection: Tracks which methods call which other methods
- Dependency Mapping: Shows relationships between classes and modules
- Call Chain Analysis: Identifies longest method call chains
- Unused Element Detection: Finds unused methods, classes, and properties
- Professional formatting with proper page breaks
- Color-coded severity indicators (Critical, High, Medium, Low)
- Emoji indicators for visual quick-reference
- Wrapped text for long descriptions
- Section headers with continuation across pages
- Quality scores with component breakdowns
The main analysis engine that orchestrates code scanning and analysis.
Key Properties:
AllElements()- Complete collection of all code elementsClassElements()- All class definitionsMethodElements()- All method definitionsModuleElements()- All module definitionsDetectedSmells()- Array of identified code smellsElementLookup- Dictionary for fast element lookupmMissingErrorHandling()- Locations missing error handlingmBareCatches()- Bare catch blocks foundmRiskyOperations()- Risky operations without protection
Key Methods:
AnalyzeProject(projectFolder As FolderItem)- Main entry point for analysisScanFileForRelationships(item As FolderItem)- Scans individual filesScanForRelationships()- Analyzes call relationships across all methodsDetectMethodCalls(code As String, callingMethod As CodeElement)- Identifies method callsDetectCodeSmells()- Runs all code smell detection algorithmsCalculateQualityScore()- Computes overall project quality scoreGetMethodElements()- Returns all method elementsGetAverageParametersPerMethod()- Calculates parameter complexityGetMethodsExceedingParameterThreshold(threshold As Integer)- Finds methods with too many parameters
Analysis Methods:
DetectGodClasses()DetectLongMethods()DetectDeepNesting()DetectMagicNumbers()DetectLongParameterLists()AnalyzeMissingErrorHandling()DetectFileOperations()DetectDatabaseOperations()DetectNetworkOperations()DetectTypeConversions()
Represents any code element (class, method, module, property, etc.)
Key Properties:
Name- Element nameFullPath- Complete path (e.g., "ClassName.MethodName")FileName- Source file nameElementType- Type of element (Class, Method, Module, Property, etc.)Code- Complete source code for the elementLOC- Lines of codeComplexity- Cyclomatic complexity scoreNestingDepth- Maximum nesting levelParameterCount- Number of parameters (for methods)OptionalParameterCount- Number of optional parametersParameters- Parameter list as stringCallsTo()- Array of methods this element callsCalledBy()- Array of methods that call this elementIsUsed- Boolean indicating if element is referenced
Key Methods:
CalculateComplexity()- Computes cyclomatic complexityCountLinesOfCode()- Counts effective LOCCalculateNestingDepth()- Determines maximum nestingExtractParameters()- Parses method parameters
Represents a detected code quality issue
Key Properties:
SmellType- Type of smell (e.g., "God Class", "Long Method")Severity- Severity level (CRITICAL, HIGH, MEDIUM, LOW)Description- Human-readable descriptionDetails- Specific metrics (e.g., "Methods: 43, LOC: 995")Recommendation- Actionable fix suggestionElement- Reference to the affected CodeElementMethodName- Name of affected method (if applicable)MetricValue- Numeric value of the metric that triggered the smell
Key Methods:
GetSeverityColor()- Returns color for severity levelGetSeverityEmoji()- Returns emoji indicator (π΄, π , π‘, π’)
Handles PDF report generation with multi-page support
Key Methods:
GenerateAnalysisReportPDF(analyzer As ProjectAnalyzer, saveFile As FolderItem) As Boolean- Main PDF generationCheckPageBreak(g As Graphics, yPos As Double, ...) As Double- Handles page breaksRenderHeader(g As Graphics, ...) As Double- Renders report headerRenderQualityScore(g As Graphics, ...) As Double- Renders quality metricsRenderCodeSmellsWithPageBreaks(g As Graphics, ...) As Double- Renders code smells with paginationRenderSingleCodeSmell(g As Graphics, smell As CodeSmell, ...) As Double- Renders individual code smellRenderErrorHandlingAnalysisWithPageBreaks(g As Graphics, ...) As Double- Renders error handling sectionRenderParameterComplexityDetailsWithPageBreaks(g As Graphics, ...) As Double- Renders parameter analysisRenderUnusedElementsWithPageBreaks(g As Graphics, ...) As Double- Renders unused elementsRenderTopComplexMethodsWithPageBreaks(g As Graphics, ...) As Double- Renders complexity rankingsWrapText(g As Graphics, text As String, maxWidth As Double) As String()- Text wrapping utility
PDF Configuration:
- Standard page size: 612 x 792 pixels (US Letter at 72 DPI)
- Top margin: 80 pixels
- Bottom margin: 100 pixels (reserve for page breaks)
- New page top margin: 120 pixels
- Line height: 14 pixels (default)
// Create analyzer
Var analyzer As New ProjectAnalyzer
// Select project folder
Var dlg As New SelectFolderDialog
dlg.Title = "Select Xojo Project Folder"
Var projectFolder As FolderItem = dlg.ShowModal()
If projectFolder <> Nil Then
// Run analysis
analyzer.AnalyzeProject(projectFolder)
// Generate PDF report
Var saveDlg As New SaveFileDialog
saveDlg.SuggestedFileName = "CodeAnalysisReport.pdf"
saveDlg.Filter = "application/pdf"
Var saveFile As FolderItem = saveDlg.ShowModal()
If saveFile <> Nil Then
Var success As Boolean = ReportGenerator.GenerateAnalysisReportPDF(analyzer, saveFile)
If success Then
MessageBox("Analysis complete! Report saved successfully.")
Else
MessageBox("Error generating report.")
End If
End If
End If// Get quality score
Var qualityScore As Double = analyzer.CalculateQualityScore()
// Get code smells
Var smells() As CodeSmell = analyzer.DetectedSmells
// Get unused elements
Var unusedMethods() As CodeElement
For Each element As CodeElement In analyzer.GetMethodElements()
If Not element.IsUsed Then
unusedMethods.Add(element)
End If
Next
// Get methods with high complexity
For Each method As CodeElement In analyzer.GetMethodElements()
If method.Complexity > 10 Then
System.DebugLog(method.FullPath + " has complexity: " + method.Complexity.ToString)
End If
Next
// Get relationship data
For Each method As CodeElement In analyzer.GetMethodElements()
System.DebugLog(method.Name + " calls " + method.CallsTo.Count.ToString + " methods")
System.DebugLog(method.Name + " is called by " + method.CalledBy.Count.ToString + " methods")
Next- File Discovery: Recursively scans project folder for Xojo source files
- XML Parsing: Parses
.xojo_project,.xojo_code,.xojo_window,.xojo_menufiles - Code Extraction: Extracts code blocks for each element (class, method, property, etc.)
- Element Creation: Creates
CodeElementobjects for each discovered element - Metrics Calculation: Computes LOC, complexity, nesting depth, parameters
- Code Smell Detection: Runs all smell detection algorithms
- Relationship Analysis: Detects method calls and builds dependency graph
- Quality Scoring: Calculates overall project quality score
- Report Generation: Creates multi-page PDF with all findings
- God Classes (>40 methods or >1000 LOC)
- Methods with >8 complexity
- Missing error handling on critical operations
- Long Methods (>50 LOC)
- Deep Nesting (>3 levels)
- Methods with >7 parameters
- Magic Numbers
- Duplicate Code patterns
- Large Classes (>30 methods)
- Minor style issues
- Potential optimizations
The overall quality score (0-100) is computed from:
-
Code Smell Density (40% weight)
- Total smells / Total LOC
- Penalty for CRITICAL and HIGH severity smells
-
Complexity (25% weight)
- Average cyclomatic complexity
- Percentage of methods with complexity >10
-
Error Handling (20% weight)
- Percentage of risky operations protected
- Bare catch block count
-
Code Organization (15% weight)
- Average method length
- Average class size
- Parameter complexity
- Header: Project name, analysis date, quality score
- Quality Score Breakdown: Component scores with visual indicators
- Code Smells: Detailed list with type, location, description, recommendation
- Error Handling Analysis: Missing handlers, bare catches, risky operations
- Unused Elements: Methods, classes, properties not referenced
- Complexity Metrics: Top 10 most complex methods
- Parameter Complexity: Methods with high parameter counts
- Relationship Analysis: Method call statistics and dependencies
- Uses
Varinstead ofDim - Uses
MessageBoxfor simple messages,MessageDialogfor confirmations - String comparison:
string.Trim = ""instead ofstring = Nil - Arrays:
myArray()declaration syntax - Case-insensitive by default
- Element Lookup Dictionary: Fast O(1) element access by FullPath
- Incremental Analysis: Only analyzes changed files (future enhancement)
- Memory Management: Clears temporary data structures after analysis
- Comment Detection: Currently removes
//comments but may need enhancement for'andRemstyles - Regex Patterns: Some complex Xojo syntax may not be fully parsed
- External References: Doesn't analyze framework or plugin code
- Dynamic Code: Cannot detect runtime-generated method calls
- Interactive HTML reports with clickable dependency graphs
- Trend analysis across multiple runs
- Custom rule configuration
- IDE integration (Xojo plugin)
- Code fix suggestions with automated refactoring
- Export to JSON/CSV for CI/CD integration
- Comparison reports (before/after refactoring)
- Table of contents with page numbers
- Charts and graphs for metrics
- Historical trend charts
- Team collaboration features
- Git integration for change tracking
The tool includes extensive debug logging via System.DebugLog():
System.DebugLog("=== DetectMethodCalls DEBUG ===")
System.DebugLog("Caller: " + callingMethod.Name)
System.DebugLog("Detected " + callingMethod.CallsTo.Count.ToString + " calls")Tip: Consider adding a DebugMode As Boolean property to toggle logging on/off.
Problem: "Methods with outgoing calls: 0"
- Solution: Ensure
ScanForRelationships()is called after all files are scanned - Check that method call detection patterns are working
Problem: "Code smells section empty in PDF"
- Solution: Verify
DetectCodeSmells()is called before report generation - Check that smell detection methods are properly implemented
Problem: "PDF content cut off at page break"
- Solution: Ensure
CheckPageBreak()is called before rendering each section - Verify estimated heights are accurate for complex content
Problem: "Type mismatch: not an array"
- Solution: Check property declarations include
()for arrays - Verify properties are Public if accessed from other classes
ProjectAnalyzer (Main Class)
βββ Properties
β βββ AllElements() As CodeElement
β βββ ClassElements() As CodeElement
β βββ MethodElements() As CodeElement
β βββ ModuleElements() As CodeElement
β βββ DetectedSmells() As CodeSmell
β βββ mMissingErrorHandling() As String
β βββ mBareCatches() As String
β βββ mRiskyOperations() As String
βββ Methods
βββ AnalyzeProject()
βββ ScanForRelationships()
βββ DetectMethodCalls()
βββ DetectCodeSmells()
βββ Calculate*() methods
CodeElement (Data Class)
βββ Properties (Name, FullPath, Code, LOC, Complexity, etc.)
βββ Methods (CalculateComplexity(), CountLinesOfCode(), etc.)
CodeSmell (Data Class)
βββ Properties (SmellType, Severity, Description, etc.)
βββ Methods (GetSeverityColor(), GetSeverityEmoji())
ReportGenerator (Utility Class)
βββ Methods (GenerateAnalysisReportPDF(), Render*(), etc.)
Developed for Xojo 2025 API 2 projects.
- Multi-page PDF report generation
- 153+ code smell detection
- Method call relationship tracking
- Error handling analysis
- Parameter complexity analysis
- Quality score calculation
- Unused element detection
- Fixed PDF header rendering (missing Return statement)
- Fixed multi-page support with g.NextPage
- Fixed code smell details rendering (Element.FullPath fallback)
- Fixed method call detection (uncommented ScanForRelationships call)
- Fixed parameter order in function signatures
- Fixed array declarations for error handling properties
[Your License Here]
Philip - Medical Professional & Software Developer Specializing in Xojo 2025 development and clinical research applications