Skip to content

feat: replace heuristic Big-O analyzer with structured complexity util#42

Merged
calebephrem merged 3 commits into
open-devhub:mainfrom
calebephrem:main
Jul 20, 2026
Merged

feat: replace heuristic Big-O analyzer with structured complexity util#42
calebephrem merged 3 commits into
open-devhub:mainfrom
calebephrem:main

Conversation

@calebephrem

Copy link
Copy Markdown
Member

What does this PR do?

Explain here what you changed and why. Doesn't need to be long, just enough
for a reviewer to understand the change without reading every line of
diff. If it was a bug fix, briefly describe what was broken. Delete this paragraph and replace it with your description.

Closes

Type of change(s)

  • Bug fix
  • New feature
  • Documentation update
  • Style / UX change
  • Refactor (no functional change)
  • Performance improvement
  • Other

Checklist

  • I've tested this change locally and it works as expected
  • bun run typecheck or npm run typecheck completes without errors
  • My commit messages follow Conventional Commits (e.g. fix: ..., feat: ..., chore: ...)
  • I've updated relevant docs (README, comments, etc.) if this change needs it
  • No leftover console.log or debug code

Screenshots / recordings (if applicable)

image

@devhub-bot devhub-bot Bot added chore maintenance, configs, formatting, dependencies ci CI configuration changes feat New feature labels Jul 20, 2026
@beetle-ai

beetle-ai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary by Beetle

This PR refactors the Big-O complexity analysis system in the QuillBot Discord bot by replacing a heuristic regex-based estimator with a structured, production-grade analyzeComplexity utility. The new implementation properly tracks loop nesting depth, classifies recursion patterns (linear, logarithmic, exponential, factorial, memoized), and produces reliable complexity indicators with detailed reasoning. This improves accuracy and maintainability of the complexity estimation feature.

📁 File Changes Summary (Consolidated across all commits):

File Status Changes Description
src/utils/analyzeComplexity.ts Added +413/-0 New structured complexity analysis utility with advanced pattern detection: loop depth profiling, function discovery, recursion classification (single/multiple calls, halving patterns, memoization detection), and confidence scoring. Replaces ad-hoc regex patterns with systematic analysis.
src/commands/code/complexity.ts Modified +12/-152 Refactored to use the new analyzeComplexity utility. Removed 140 lines of heuristic scoring logic, regex patterns, and manual flag tracking. Now delegates analysis to the utility and formats results into Discord embeds.
CHANGELOG.md Modified +8/-2 Updated changelog for v1.2.0 with feature description and issue references (#41, #32).
.github/pull_request_template.md Added +38/-0 New PR template with sections for description, issue linking, change type, checklist (testing, typecheck, conventional commits, docs, debug code), and optional screenshots.
package.json Modified +2/-2 Added typecheck script (tsc --noEmit) and removed dev script. Updated lint:fix formatting.

Total Changes: 5 files changed, +473 additions, -156 deletions

🗺️ Walkthrough:

graph TD
A["User Input: Code Block"] --> B["parseCodeBlock & parseCodeCommandInput"]
B --> C["analyzeComplexity Utility"]
C --> D["stripDecorators"]
D --> E["loopDepthProfile"]
E --> F["Loop Analysis"]
F --> G["Complexity Ranking"]
C --> H["findFunctions"]
H --> I["analyzeRecursion"]
I --> J["Recursion Classification"]
J --> K["Memoization Detection"]
K --> G
G --> L["Determine Final Complexity"]
L --> M["Calculate Confidence"]
M --> N["Generate Indicators & Reasoning"]
N --> O["EmbedBuilder"]
O --> P["Discord Message Response"]
Loading

🎯 Key Changes:

  • New analyzeComplexity Utility: Comprehensive 413-line module that systematically analyzes code complexity through multiple detection layers:
  • Loop Depth Profiling: Tracks nesting depth across the entire code, distinguishing between regular blocks and loop blocks
  • Function Discovery: Identifies function declarations (traditional, arrow, async) and their boundaries
  • Recursion Classification: Detects single vs. multiple recursive calls, halving patterns (divide-and-conquer), memoization, and backtracking scenarios
  • Pattern Detection: Identifies sorting operations, collection helpers (map/filter/reduce), and logarithmic operations
  • Refactored Complexity Command: Reduced from 179 lines to 40 lines of analysis logic by delegating to the utility. Removed 140+ lines of fragile regex patterns and manual scoring
  • Improved Accuracy: New system properly handles:
  • Nested loop depth (O(n³), O(n^k) for 3+ levels)
  • Divide-and-conquer patterns (O(n log n) for multiple halving calls)
  • Memoized recursion (O(n) instead of O(2ⁿ))
  • Backtracking patterns (O(n!) for recursive calls inside loops)
  • Brace-less loops and collection iteration helpers
  • Better Confidence Scoring: High confidence for exponential/factorial recursion or nested loops; Medium for single recursion or basic loops; Low otherwise
  • Project Infrastructure: Added PR template for standardized contributions and typecheck script for TypeScript validation

📊 Impact Assessment:

  • Security: ✅ No security implications. The utility operates on user-provided code strings without execution or external calls. Regex patterns are well-scoped and safe.
  • Performance: ✅ Improved. The new utility uses single-pass analysis (loop depth profiling, function discovery) instead of multiple regex tests. Complexity analysis is O(n) where n is code length, with minimal overhead.
  • Maintainability: ✅ Significantly improved. The new utility is modular with clear separation of concerns (loop analysis, recursion analysis, pattern detection). Code is well-documented with helper functions (matchBrace, matchParen, stripDecorators). Easier to extend with new patterns or recursion types.
  • Testing: ⚠️ Moderate concern. The PR removes 140+ lines of tested logic but doesn't show new test coverage for the utility. The complexity analysis is now centralized (good for testing), but test cases for edge cases (brace-less loops, arrow functions, memoization patterns) should be added. The new typecheck script helps catch type errors early.
⚙️ Settings

Severity Threshold: Medium — Balanced feedback — medium and high severity issues only.Change in Settings
Custom Rules: Define your own review rules — Set Custom Rules
PR Summary: Configure PR summary — Change in Settings

📖 User Guide
  • Once repos are connected, PR analysis is automatically enabled. You can disable analysis for this repo from beetleai.dev/analysis
  • Comment @beetle on any PR to start analysis manually
  • Comment @beetle stop to stop any ongoing analysis

Follow us: Beetle · X · LinkedIn


try {
if (!code?.trim()) {
if (!code.trim()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code calls .trim() on code which is typed as string | undefined, but the optional chaining operator (?.) was removed. This will throw a runtime error if code is undefined at this point.

Confidence: 5/5

Suggested Fix
Suggested change
if (!code.trim()) {
if (!code?.trim()) {

The optional chaining operator (?.) safely handles the case where code might be undefined, preventing a "Cannot read property 'trim' of undefined" runtime error.

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/commands/code/complexity.ts around line 93, the code calls .trim() on the
variable `code` which is typed as `string | undefined`. The original code used optional
chaining (`code?.trim()`) to safely handle the undefined case, but this was removed
during refactoring. Restore the optional chaining operator to prevent runtime errors
when code is undefined.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is already check for that 😭

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@calebephrem I encountered an error while generating a response. Please try again.

Comment on lines +33 to +44
function matchBrace(str: string, openIndex: number): number {
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "{") depth++;
else if (ch === "}") {
depth--;
if (depth === 0) return i;
}
}
return -1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The matchBrace function doesn't validate that openIndex is within valid bounds. If called with a negative index or an index >= str.length, the function behavior becomes unpredictable. While JavaScript's string indexing is forgiving, this could lead to subtle bugs if the function is called with invalid indices from other parts of the code.

Confidence: 4/5

Suggested Fix
Suggested change
function matchBrace(str: string, openIndex: number): number {
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "{") depth++;
else if (ch === "}") {
depth--;
if (depth === 0) return i;
}
}
return -1;
}
function matchBrace(str: string, openIndex: number): number {
if (openIndex < 0 || openIndex >= str.length) return -1;
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "{") depth++;
else if (ch === "}") {
depth--;
if (depth === 0) return i;
}
return -1;
}

Add bounds validation at the start of the function to ensure openIndex is within the valid range [0, str.length).

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/utils/analyzeComplexity.ts around line 33, add bounds validation to the
matchBrace function to ensure openIndex is within valid range [0, str.length).
This prevents undefined behavior if the function is called with invalid indices.

📍 This suggestion applies to lines 33-44

Comment on lines +47 to +58
function matchParen(str: string, openIndex: number): number {
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "(") depth++;
else if (ch === ")") {
depth--;
if (depth === 0) return i;
}
}
return -1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to matchBrace, the matchParen function lacks bounds validation for the openIndex parameter. This could cause issues if called with invalid indices, leading to unpredictable behavior or incorrect results.

Confidence: 4/5

Suggested Fix
Suggested change
function matchParen(str: string, openIndex: number): number {
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "(") depth++;
else if (ch === ")") {
depth--;
if (depth === 0) return i;
}
}
return -1;
}
function matchParen(str: string, openIndex: number): number {
if (openIndex < 0 || openIndex >= str.length) return -1;
let depth = 0;
for (let i = openIndex; i < str.length; i++) {
const ch = str.charAt(i);
if (ch === "(") depth++;
else if (ch === ")") {
depth--;
if (depth === 0) return i;
}
return -1;
}

Add bounds validation at the start of the function to ensure openIndex is within the valid range [0, str.length).

Prompt for AI

Copy this prompt to your AI IDE to fix this issue locally:

In src/utils/analyzeComplexity.ts around line 47, add bounds validation to the
matchParen function to ensure openIndex is within valid range [0, str.length).
This prevents undefined behavior if the function is called with invalid indices.

📍 This suggestion applies to lines 47-58

@devhub-bot

devhub-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Note

Linting checks passed successfully 🎉

All formatting and code quality checks are clean.

You're good to merge 🚀

@calebephrem
calebephrem merged commit b17733f into open-devhub:main Jul 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore maintenance, configs, formatting, dependencies ci CI configuration changes feat New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue with complexity command (inaccurate)

1 participant