Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions frontend/src/components/CodeComplexityProfiler.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState } from 'react';
import * as babel from '@babel/standalone';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

jq -e '
  (.dependencies // {})["`@babel/standalone`"] //
  (.devDependencies // {})["`@babel/standalone`"]
' frontend/package.json

Repository: Canopus-Labs/PrepPilot

Length of output: 165


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- manifests and lockfiles ---'
git ls-files '*package.json' '*package-lock.json' '*yarn.lock' '*pnpm-lock.yaml' '*npm-shrinkwrap.json'

printf '%s\n' '--- frontend manifest ---'
cat frontend/package.json

printf '%s\n' '--- relevant source references ---'
rg -n -C 4 '`@babel/standalone`|babel\.(parse|traverse)|babel\.packages' frontend/src frontend/package.json

printf '%s\n' '--- lockfile references ---'
rg -n -C 2 '`@babel/standalone`|node_modules/@babel/standalone|babel/standalone' . \
  -g 'package-lock.json' -g 'yarn.lock' -g 'pnpm-lock.yaml' -g 'npm-shrinkwrap.json' || true

Repository: Canopus-Labs/PrepPilot

Length of output: 3637


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- component ---'
cat -n frontend/src/components/CodeComplexityProfiler.jsx

printf '%s\n' '--- root package configuration ---'
cat package.json

printf '%s\n' '--- all lockfile package entries for the dependency ---'
for lockfile in package-lock.json frontend/package-lock.json backend/package-lock.json; do
  if [ -f "$lockfile" ]; then
    printf '%s\n' "--- $lockfile ---"
    jq -r '
      if .packages then
        .packages | to_entries[] | select(.key | contains("`@babel/standalone`")) | .key + " " + (.value.version // "")
      elif .dependencies then
        paths(scalars) as $p | select(($p | join("/")) | contains("`@babel/standalone`")) | (($p | join("/")) + " " + (getpath($p) | tostring))
      else empty end
    ' "$lockfile" 2>/dev/null || true
  fi
done

Repository: Canopus-Labs/PrepPilot

Length of output: 4005


🌐 Web query:

@babel/standalone parse traverse API Babel.packages official documentation

💡 Result:

The @babel/standalone package provides access to internal Babel tooling packages, including parser and traverse, through the Babel.packages object [1][2]. When you load @babel/standalone in a browser environment, it exposes a global Babel object that contains these packages [1]. You can access them as follows: Babel.packages.parser [1][2] Babel.packages.traverse [1][2] Other available packages include Babel.packages.generator, Babel.packages.template, and Babel.packages.types [1][2]. Important usage notes: - These internal packages are exposed specifically for use within non-Node.js (browser) environments where standard module imports are not available [3]. - While these packages are made available, @babel/standalone does not provide a direct top-level parse API outside of these namespaced packages [4]. - You should generally prefer importing these packages directly (e.g., import { parse } from "@babel/parser") if you are using a bundler or working in a Node.js environment [3].

Citations:


Declare @babel/standalone and use its supported APIs.

Add @babel/standalone to frontend/package.json and update frontend/package-lock.json. The current babel.parse and babel.traverse calls are not top-level @babel/standalone APIs; use babel.packages.parser and babel.packages.traverse instead.

🤖 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/CodeComplexityProfiler.jsx` at line 2, Declare
`@babel/standalone` in frontend/package.json and synchronize
frontend/package-lock.json. In CodeComplexityProfiler, replace unsupported
top-level babel.parse and babel.traverse calls with the supported
babel.packages.parser and babel.packages.traverse APIs.


const CodeComplexityProfiler = ({ code }) => {
const [complexity, setComplexity] = useState(null);
const [error, setError] = useState(null);

const analyzeCode = () => {
try {
setError(null);

// Parse code to AST
const ast = babel.parse(code, {
presets: ['env'],
});

let loopCount = 0;
let maxDepth = 0;

// Simple custom traversal to detect loops
babel.traverse(ast, {
Comment on lines +13 to +21

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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Official Babel documentation for @babel/standalone: how should an application access the parser and traversal APIs, and are Babel.parseandBabel.traverse supported top-level APIs?

💡 Result:

In @babel/standalone, the parser and traversal APIs are not directly exposed as top-level methods on the global Babel object [1][2]. Instead, they are accessible through the Babel.packages object [1][2]. To access these functionalities, you should use the following paths: - Parser: Babel.packages.parser [1][2] - Traversal: Babel.packages.traverse [1][2] The methods Babel.parse and Babel.traverse are not supported as top-level APIs on the Babel object [1][2]. You must access them via the namespaced properties shown above. For example, if you wish to use the parser, you would access it via Babel.packages.parser. Likewise, traversal is accessed via Babel.packages.traverse [1][2]. The full list of internal packages exposed on the Babel.packages object includes: - Babel.packages.generator [1][2] - Babel.packages.parser [1][2] - Babel.packages.template [1][2] - Babel.packages.traverse [1][2] - Babel.packages.types [1][2]

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

file="$(git ls-files | grep -F 'frontend/src/components/CodeComplexityProfiler.jsx' | head -n1)"
printf '%s\n' "FILE=$file"
wc -l "$file"
sed -n '1,180p' "$file"

printf '%s\n' '--- frontend/package.json ---'
cat frontend/package.json

printf '%s\n' '--- Babel API references ---'
rg -n --glob '!node_modules/**' '`@babel/standalone`|babel\.(parse|traverse)|babel\.packages\.(parser|traverse)' frontend

Repository: Canopus-Labs/PrepPilot

Length of output: 4869


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- package manifests and lockfiles ---'
git ls-files | grep -E '(^|/)(package(-lock)?\.json|pnpm-lock\.yaml|yarn\.lock)$' || true

printf '%s\n' '--- `@babel/standalone` declarations and lockfile entries ---'
rg -n --hidden --glob '!**/.git/**' --glob '!**/node_modules/**' \
  '"`@babel/standalone`"|`@babel/standalone` frontend|`@babel/standalone`' . || true

printf '%s\n' '--- component call sites ---'
rg -n --glob '!**/node_modules/**' 'CodeComplexityProfiler|analyzeCode|setComplexity|setError' frontend/src frontend 2>/dev/null || true

printf '%s\n' '--- relevant source structure ---'
ast-grep outline frontend/src/components/CodeComplexityProfiler.jsx

Repository: Canopus-Labs/PrepPilot

Length of output: 20884


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import json
from pathlib import Path

source = Path("frontend/src/components/CodeComplexityProfiler.jsx").read_text()
manifest = json.loads(Path("frontend/package.json").read_text())
lock = json.loads(Path("frontend/package-lock.json").read_text())

print("frontend_dependency_declared=", "`@babel/standalone`" in manifest.get("dependencies", {}) or "`@babel/standalone`" in manifest.get("devDependencies", {}))
print("frontend_lock_root_declared=", "`@babel/standalone`" in lock.get("packages", {}).get("", {}).get("dependencies", {}))
print("frontend_lock_package_present=", any(
    key.endswith("/node_modules/@babel/standalone") or key == "node_modules/@babel/standalone"
    for key in lock.get("packages", {})
))
print("top_level_parse_call=", "babel.parse(" in source)
print("namespaced_parse_call=", "babel.packages.parser.parse(" in source)
print("top_level_traverse_call=", "babel.traverse(" in source)
print("namespaced_traverse_call=", "babel.packages.traverse(" in source)

for node in ("ForStatement", "WhileStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement"):
    print(f"visitor_{node}=", f"{node}(path)" in source)
print("complexity_cleared_on_error=", "setComplexity(null)" in source[source.index("} catch"):])
PY

printf '%s\n' '--- frontend lockfile package metadata ---'
python3 - <<'PY'
import json
from pathlib import Path
lock = json.loads(Path("frontend/package-lock.json").read_text())
for key, value in lock.get("packages", {}).items():
    if "babel" in key.lower():
        print(key, value.get("version"))
PY

printf '%s\n' '--- root package declarations ---'
cat package.json

Repository: Canopus-Labs/PrepPilot

Length of output: 1741


Fix the Babel dependency and analyzer state before merging.

  • Add @babel/standalone to frontend/package.json and its lockfile.
  • Use babel.packages.parser.parse and babel.packages.traverse. The top-level calls are unsupported.
  • Add visitors for ForInStatement, ForOfStatement, and DoWhileStatement if all loops must count.
  • Clear complexity in the error path to prevent stale results.
🤖 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/CodeComplexityProfiler.jsx` around lines 13 - 21, Add
`@babel/standalone` to frontend/package.json and the lockfile, then update
CodeComplexityProfiler to parse and traverse through babel.packages.parser.parse
and babel.packages.traverse. Extend its traversal visitors to count
ForInStatement, ForOfStatement, and DoWhileStatement, and clear the complexity
state in the error path so stale results are not retained.

ForStatement(path) {
loopCount++;
const depth = path.getAncestry().filter(p => p.isLoop()).length;
maxDepth = Math.max(maxDepth, depth);
},
WhileStatement(path) {
loopCount++;
const depth = path.getAncestry().filter(p => p.isLoop()).length;
maxDepth = Math.max(maxDepth, depth);
}
});
Comment on lines +21 to +32

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 | ⚡ Quick win

Include all JavaScript loop node types.

for...in, for...of, and do...while loops are not counted. For example, a single for (const item of items) loop reports zero loops and O(1). Add visitors for ForInStatement, ForOfStatement, and DoWhileStatement.

Proposed fix
       babel.packages.traverse(ast, {
         ForStatement(path) {
           loopCount++;
           const depth = path.getAncestry().filter(p => p.isLoop()).length;
           maxDepth = Math.max(maxDepth, depth);
         },
+        ForInStatement(path) {
+          loopCount++;
+          const depth = path.getAncestry().filter(p => p.isLoop()).length;
+          maxDepth = Math.max(maxDepth, depth);
+        },
+        ForOfStatement(path) {
+          loopCount++;
+          const depth = path.getAncestry().filter(p => p.isLoop()).length;
+          maxDepth = Math.max(maxDepth, depth);
+        },
         WhileStatement(path) {
           loopCount++;
           const depth = path.getAncestry().filter(p => p.isLoop()).length;
           maxDepth = Math.max(maxDepth, depth);
+        },
+        DoWhileStatement(path) {
+          loopCount++;
+          const depth = path.getAncestry().filter(p => p.isLoop()).length;
+          maxDepth = Math.max(maxDepth, depth);
         }
       });
🤖 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/CodeComplexityProfiler.jsx` around lines 21 - 32,
Extend the loop visitors in the Babel traversal used by the complexity profiler
to include ForInStatement, ForOfStatement, and DoWhileStatement alongside
ForStatement and WhileStatement. Ensure each new visitor increments loopCount
and updates maxDepth using the same ancestry-based depth calculation.


let bigO = 'O(1)';
if (maxDepth === 1) bigO = 'O(n)';
if (maxDepth === 2) bigO = 'O(n^2)';
if (maxDepth >= 3) bigO = 'O(n^3) or worse';

setComplexity({
totalLoops: loopCount,
maxNesting: maxDepth,
estimatedTimeComplexity: bigO
});

} catch (err) {
setError("Failed to parse code. Please ensure valid JavaScript.");
console.error(err);
}
Comment on lines +45 to +48

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

Clear the previous result when parsing fails.

If a valid analysis is followed by invalid code, complexity retains the old result. The UI then shows stale loop metrics with the parse error. Clear complexity in the catch block.

Proposed fix
     } catch (err) {
+      setComplexity(null);
       setError("Failed to parse code. Please ensure valid JavaScript.");
       console.error(err);
     }
📝 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
} catch (err) {
setError("Failed to parse code. Please ensure valid JavaScript.");
console.error(err);
}
} catch (err) {
setComplexity(null);
setError("Failed to parse code. Please ensure valid JavaScript.");
console.error(err);
}
🤖 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/CodeComplexityProfiler.jsx` around lines 45 - 48,
Update the parse-error catch block in CodeComplexityProfiler to clear the
existing complexity result before setting the parse error, ensuring stale
analysis metrics are not displayed after invalid code is submitted.

};

return (
<div className="p-4 bg-gray-900 rounded-xl shadow-lg border border-gray-700 mt-4">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold text-white">AST Code Complexity Profiler</h2>
<button
onClick={analyzeCode}
className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-500 transition-colors"
>
Analyze Complexity
</button>
</div>

{error && (
<div className="text-red-400 mb-2">{error}</div>
)}

{complexity && (
<div className="bg-gray-800 p-4 rounded-lg">
<div className="grid grid-cols-3 gap-4 text-center">
<div className="p-2 border border-gray-600 rounded">
<div className="text-gray-400 text-sm">Total Loops</div>
<div className="text-2xl font-bold text-white">{complexity.totalLoops}</div>
</div>
<div className="p-2 border border-gray-600 rounded">
<div className="text-gray-400 text-sm">Max Nesting Depth</div>
<div className="text-2xl font-bold text-white">{complexity.maxNesting}</div>
</div>
<div className="p-2 border border-purple-500 rounded bg-purple-900 bg-opacity-20">
<div className="text-purple-300 text-sm">Estimated Big-O</div>
<div className="text-2xl font-bold text-purple-400">{complexity.estimatedTimeComplexity}</div>
</div>
</div>
</div>
)}
</div>
);
};

export default CodeComplexityProfiler;
Loading