Skip to content

feat: add AST-based code complexity profiler - #1864

Merged
KaranUnique merged 11 commits into
Canopus-Labs:mainfrom
bindusreeseetha:feat/ast-complexity-profiler
Aug 12, 2026
Merged

feat: add AST-based code complexity profiler#1864
KaranUnique merged 11 commits into
Canopus-Labs:mainfrom
bindusreeseetha:feat/ast-complexity-profiler

Conversation

@bindusreeseetha

@bindusreeseetha bindusreeseetha commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a client-side AST complexity analyzer for JavaScript/TypeScript code
  • Detect nested loops and common linear array traversals
  • Detect recursion signals and common dynamic allocations
  • Display estimated time and space complexity in the compiler UI
  • Provide real-time complexity feedback while editing JavaScript
  • Add unit tests for common complexity cases and syntax errors

Notes

The profiler is intentionally implemented as a static heuristic. It provides an estimated complexity rather than claiming a formal Big-O proof.

Closes #1745

Summary

  • Added client-side AST-based complexity analysis for JavaScript, JSX, and TypeScript.
  • Added real-time complexity feedback in the compiler with 300 ms debounce.
  • Added time and space complexity estimates, metrics, explanations, warnings, and syntax-error guidance.
  • Added Vitest coverage for common complexity cases and invalid JavaScript.
  • Added @babel/parser as a frontend dependency.

Ready to merge.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Babel-based analyzer for JavaScript, JSX, and TypeScript. The compiler runs analysis with a 300 ms debounce and renders results through ComplexityProfiler.

Changes

Complexity profiler

Layer / File(s) Summary
AST analysis and validation
frontend/package.json, frontend/src/utils/complexityAnalyzer.js, frontend/src/utils/complexityAnalyzer.test.js
Adds parser-backed time and space complexity estimates, loop metrics, recursion and allocation detection, structured parse-error results, and Vitest coverage.
Debounced compiler integration
frontend/src/components/Compiler.jsx
Adds TypeScript support and runs JavaScript or TypeScript analysis after a 300 ms debounce.
Profiler result rendering
frontend/src/components/ComplexityProfiler.jsx
Displays complexity estimates, metrics, explanations, warnings, empty states, unsupported-language notices, and syntax-error guidance.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Compiler
  participant ComplexityAnalyzer
  participant ComplexityProfiler
  Compiler->>ComplexityAnalyzer: Analyze JavaScript or TypeScript after 300 ms debounce
  ComplexityAnalyzer-->>Compiler: Return complexity results
  Compiler->>ComplexityProfiler: Pass analysis and language support state
  ComplexityProfiler-->>Compiler: Render complexity details
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: an AST-based code complexity profiler.
Linked Issues check ✅ Passed The changes implement the AST-based, client-side, real-time heuristic complexity profiler requested in [#1745].
Out of Scope Changes check ✅ Passed All changes support the profiler feature, including parsing, analysis, UI integration, dependency setup, and tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/Compiler.jsx`:
- Around line 37-45: Enable TypeScript analysis consistently across the compiler
UI: in frontend/src/components/Compiler.jsx lines 37-45, add the TypeScript
language configuration and trigger analyzeJavaScriptComplexity for it; in
frontend/src/components/Compiler.jsx lines 157-161, set supported={true} for
that selection; and in frontend/src/components/ComplexityProfiler.jsx lines
9-12, keep the TypeScript message only when compiler support is enabled,
otherwise describe the profiler as JavaScript-only.

In `@frontend/src/utils/complexityAnalyzer.js`:
- Around line 53-58: The AST walk’s dynamic-allocation detection must also
recognize member calls to Array.prototype.map and filter, alongside literals,
new expressions, and push calls. Update the CallExpression handling to mark
dynamicAllocation for these method names, and add regression tests covering map
and filter space analysis.
- Around line 81-88: Update the complexity analysis around arrayMethodLoops and
the surrounding loop-depth tracking to distinguish array-method callbacks nested
within one another from literal loop nesting. Track callback traversal depth
while visiting linear array methods, and combine it with literal loop depth so
nested map calls and a map inside a for loop are treated as O(n) rather than
multiplicative. Add regression tests covering both nested map calls and a loop
containing map.
- Around line 61-65: Update both complexity-analysis passes around the walk
callbacks to track the enclosing callable and classify a call as recursive only
when it targets that callable, rather than any name in the global functionNames
set. Preserve recursion detection for declarations and add support for
variable-assigned recursive arrow functions. Add tests covering an ordinary
helper call and a recursive arrow-function implementation.
- Around line 3-5: Update the LOOP_TYPES set in complexityAnalyzer.js to include
ForInStatement and ForOfStatement so these loop constructs contribute to
complexity like the existing loop types. Add regression tests covering both
for...in and for...of analysis while preserving current behavior for other
constructs.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9173191e-c6cd-4423-a4d2-8c0883ff5143

📥 Commits

Reviewing files that changed from the base of the PR and between 18a34ee and 84d7b59.

📒 Files selected for processing (5)
  • frontend/package.json
  • frontend/src/components/Compiler.jsx
  • frontend/src/components/ComplexityProfiler.jsx
  • frontend/src/utils/complexityAnalyzer.js
  • frontend/src/utils/complexityAnalyzer.test.js

Comment thread frontend/src/components/Compiler.jsx
Comment thread frontend/src/utils/complexityAnalyzer.js Outdated
Comment thread frontend/src/utils/complexityAnalyzer.js Outdated
Comment thread frontend/src/utils/complexityAnalyzer.js Outdated
Comment thread frontend/src/utils/complexityAnalyzer.js
@github-actions github-actions Bot added the merge ready PR is mergeable and has no conflicts label Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/utils/complexityAnalyzer.test.js`:
- Around line 51-69: Update analyzeJavaScriptComplexity and the two traversal
tests so nested map callbacks and map calls inside outer loops are not
classified as definite O(n). Track callback nesting and loop-contained callbacks
as multiple or unknown input dimensions, returning the established
multidimensional or inconclusive complexity representation while preserving
loopCount semantics.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 83f9b4af-2e1e-4936-81ba-263241c1d537

📥 Commits

Reviewing files that changed from the base of the PR and between 84d7b59 and a3c6ced.

📒 Files selected for processing (4)
  • frontend/src/components/Compiler.jsx
  • frontend/src/components/ComplexityProfiler.jsx
  • frontend/src/utils/complexityAnalyzer.js
  • frontend/src/utils/complexityAnalyzer.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/utils/complexityAnalyzer.js

Comment on lines +51 to +69
it("treats nested map callbacks as one linear traversal", () => {
const result = analyzeJavaScriptComplexity(`
rows.map((row) => row.map((value) => value * 2));
`);

expect(result.timeComplexity).toBe("O(n)");
expect(result.metrics.loopCount).toBe(0);
});

it("treats a map inside a loop as linear under this heuristic", () => {
const result = analyzeJavaScriptComplexity(`
for (const row of rows) {
row.map((value) => value * 2);
}
`);

expect(result.timeComplexity).toBe("O(n)");
expect(result.metrics.loopCount).toBe(1);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not lock nested traversals to O(n).

Lines 51-69 contain two traversal levels. rows.map(... row.map(...)) can traverse rows × row.length. A map inside an outer loop has the same risk. Treating both cases as O(n) can hide the quadratic bottleneck that this profiler must identify.

Update the heuristic and these tests to account for callback nesting and callbacks inside loops. If input dimensions are unknown, return a multidimensional or inconclusive estimate instead of a definite O(n) result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/utils/complexityAnalyzer.test.js` around lines 51 - 69, Update
analyzeJavaScriptComplexity and the two traversal tests so nested map callbacks
and map calls inside outer loops are not classified as definite O(n). Track
callback nesting and loop-contained callbacks as multiple or unknown input
dimensions, returning the established multidimensional or inconclusive
complexity representation while preserving loopCount semantics.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/Compiler.jsx`:
- Line 105: Update the language selector styling in Compiler.jsx to preserve a
visible keyboard focus indicator: remove focus:outline-none or replace it with
an equivalent visible focus-visible outline/ring utility. Keep the existing
non-focus styling unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d39095fd-65c3-4458-a198-b7bf393de4d8

📥 Commits

Reviewing files that changed from the base of the PR and between 18a34ee and a3c6ced.

📒 Files selected for processing (5)
  • frontend/package.json
  • frontend/src/components/Compiler.jsx
  • frontend/src/components/ComplexityProfiler.jsx
  • frontend/src/utils/complexityAnalyzer.js
  • frontend/src/utils/complexityAnalyzer.test.js
🚧 Files skipped from review as they are similar to previous changes (4)
  • frontend/package.json
  • frontend/src/utils/complexityAnalyzer.js
  • frontend/src/utils/complexityAnalyzer.test.js
  • frontend/src/components/ComplexityProfiler.jsx

value={language}
onChange={handleLanguageChange}
className="px-3 py-1.5 rounded-lg bg-gray-700 text-white text-sm font-semibold focus:outline-none border border-gray-500"
className="rounded-lg border border-gray-500 bg-gray-700 px-3 py-1.5 text-sm font-semibold text-white focus:outline-none"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep a visible focus indicator on the language selector.

focus:outline-none removes the browser focus indicator, and this class adds no replacement. Keyboard users may not be able to identify the focused selector. Retain the outline or add a visible :focus-visible ring.

Proposed fix
-                  className="rounded-lg border border-gray-500 bg-gray-700 px-3 py-1.5 text-sm font-semibold text-white focus:outline-none"
+                  className="rounded-lg border border-gray-500 bg-gray-700 px-3 py-1.5 text-sm font-semibold text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className="rounded-lg border border-gray-500 bg-gray-700 px-3 py-1.5 text-sm font-semibold text-white focus:outline-none"
className="rounded-lg border border-gray-500 bg-gray-700 px-3 py-1.5 text-sm font-semibold text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/Compiler.jsx` at line 105, Update the language
selector styling in Compiler.jsx to preserve a visible keyboard focus indicator:
remove focus:outline-none or replace it with an equivalent visible focus-visible
outline/ring utility. Keep the existing non-focus styling unchanged.

@KaranUnique
KaranUnique merged commit be63d10 into Canopus-Labs:main Aug 12, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Dynamic AST-based (Abstract Syntax Tree) Code Complexity Profiler

2 participants