-
Notifications
You must be signed in to change notification settings - Fork 141
feat: add AST-based code complexity profiler #1864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e88e55b
7e28b99
9c90d0b
8bd918a
9209dc6
f132d42
84d7b59
dd07712
cd4aab2
b624d26
a3c6ced
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,7 +1,9 @@ | ||||||
| import React, { useState } from "react"; | ||||||
| import React, { useEffect, useState } from "react"; | ||||||
| import Editor from "@monaco-editor/react"; | ||||||
| import { Play } from "lucide-react"; | ||||||
| import DashboardLayout from "./Layouts/DashboardLayout"; | ||||||
| import ComplexityProfiler from "./ComplexityProfiler"; | ||||||
| import { analyzeJavaScriptComplexity } from "../utils/complexityAnalyzer"; | ||||||
|
|
||||||
| const RAPIDAPI_KEY = import.meta.env.VITE_REACT_APP_RAPIDAPI_KEY; | ||||||
|
|
||||||
|
|
@@ -10,33 +12,39 @@ const LANGUAGE_MAP = { | |||||
| "62": "java", | ||||||
| "71": "python", | ||||||
| "63": "javascript", | ||||||
| "74": "typescript", | ||||||
| }; | ||||||
|
|
||||||
| const Compiler = () => { | ||||||
| const [language, setLanguage] = useState("62"); // Default Java | ||||||
| const codeTemplates = { | ||||||
| "54": `#include <iostream> | ||||||
| using namespace std; | ||||||
| int main() { | ||||||
| cout << "Hello World" << endl; | ||||||
| return 0; | ||||||
| }`, | ||||||
| "62": `public class Main { | ||||||
| public static void main(String[] args) { | ||||||
| System.out.println("Hello World"); | ||||||
| } | ||||||
| }`, | ||||||
| "54": `#include <iostream>\nusing namespace std;\nint main() {\n cout << "Hello World" << endl;\n return 0;\n}`, | ||||||
| "62": `public class Main {\n public static void main(String[] args) {\n System.out.println("Hello World");\n }\n}`, | ||||||
| "71": `print("Hello World")`, | ||||||
| "63": `console.log("Hello World");` | ||||||
| "63": `console.log("Hello World");`, | ||||||
| "74": `const message: string = "Hello World";\nconsole.log(message);`, | ||||||
| }; | ||||||
| const [code, setCode] = useState(codeTemplates[language]); | ||||||
| const [output, setOutput] = useState("No output"); | ||||||
| const [complexity, setComplexity] = useState(() => | ||||||
| analyzeJavaScriptComplexity(codeTemplates["63"]) | ||||||
| ); | ||||||
|
|
||||||
| const handleLanguageChange = (e) => { | ||||||
| const lang = e.target.value; | ||||||
| setLanguage(lang); | ||||||
| setCode(codeTemplates[lang] || "// Select a supported language"); | ||||||
| }; | ||||||
| const [output, setOutput] = useState("No output"); | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| if (language !== "63" && language !== "74") return; | ||||||
|
|
||||||
| const timer = setTimeout(() => { | ||||||
| setComplexity(analyzeJavaScriptComplexity(code)); | ||||||
| }, 300); | ||||||
|
|
||||||
| return () => clearTimeout(timer); | ||||||
| }, [code, language]); | ||||||
|
|
||||||
| const handleRun = async () => { | ||||||
| setOutput("Running..."); | ||||||
|
|
@@ -76,16 +84,16 @@ int main() { | |||||
| return ( | ||||||
| <> | ||||||
| <DashboardLayout /> | ||||||
| <div className="min-h-screen bg-gradient-to-b from-[#0f172a] to-[#0b1120] text-gray-100 px-6 py-10 font-poppins"> | ||||||
| <div className="max-w-4xl mx-auto mb-10 text-center"> | ||||||
| <h1 className="text-3xl md:text-4xl font-bold text-violet-400 mb-2">Instant Code Compiler</h1> | ||||||
| <p className="text-base md:text-lg text-gray-200 mb-2"> | ||||||
| <div className="min-h-screen bg-gradient-to-b from-[#0f172a] to-[#0b1120] px-6 py-10 font-poppins text-gray-100"> | ||||||
| <div className="mx-auto mb-10 max-w-4xl text-center"> | ||||||
| <h1 className="mb-2 text-3xl font-bold text-violet-400 md:text-4xl">Instant Code Compiler</h1> | ||||||
| <p className="mb-2 text-base text-gray-200 md:text-lg"> | ||||||
| Instantly write, run, and test your code in multiple languages. No setup required—just code and see results! | ||||||
| </p> | ||||||
| </div> | ||||||
| <div className="max-w-6xl mx-auto flex flex-col md:flex-row gap-6"> | ||||||
| <div className="flex-1 flex flex-col bg-white/10 backdrop-blur-lg border border-white/10 rounded shadow-xl overflow-hidden min-h-[360px]"> | ||||||
| <div className="flex justify-between items-center bg-gradient-to-r from-gray-600 to-gray-600 px-4 py-3"> | ||||||
| <div className="mx-auto flex max-w-6xl flex-col gap-6 md:flex-row"> | ||||||
| <div className="flex min-h-[360px] flex-1 flex-col overflow-hidden rounded border border-white/10 bg-white/10 shadow-xl backdrop-blur-lg"> | ||||||
| <div className="flex items-center justify-between bg-gradient-to-r from-gray-600 to-gray-600 px-4 py-3"> | ||||||
| <div className="flex items-center gap-3 text-sm text-white"> | ||||||
| <label htmlFor="language" className="text-lg"> | ||||||
| Language: | ||||||
|
|
@@ -94,27 +102,27 @@ int main() { | |||||
| id="language" | ||||||
| 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" | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
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
Suggested change
🤖 Prompt for AI Agents |
||||||
| > | ||||||
| <option value="54">C++</option> | ||||||
| <option value="62">Java</option> | ||||||
| <option value="71">Python</option> | ||||||
| <option value="63">JavaScript</option> | ||||||
| <option value="74">TypeScript</option> | ||||||
| </select> | ||||||
| </div> | ||||||
| <button | ||||||
| type="button" | ||||||
| onClick={handleRun} | ||||||
| aria-label="Run code" | ||||||
| className="flex items-center gap-2 px-5 py-2 bg-violet-500 text-white font-semibold rounded-xl | ||||||
| hover:bg-violet-700 transition shadow-md" | ||||||
| className="flex items-center gap-2 rounded-xl bg-violet-500 px-5 py-2 font-semibold text-white shadow-md transition hover:bg-violet-700" | ||||||
| > | ||||||
| <Play className="w-4 h-4" /> | ||||||
| <Play className="h-4 w-4" /> | ||||||
| Run | ||||||
| </button> | ||||||
| </div> | ||||||
|
|
||||||
| <div className="flex-1 min-h-[300px]" aria-label="Code editor"> | ||||||
| <div className="min-h-[300px] flex-1" aria-label="Code editor"> | ||||||
| <Editor | ||||||
| height="400px" | ||||||
| language={LANGUAGE_MAP[language] || "javascript"} | ||||||
|
|
@@ -134,20 +142,27 @@ int main() { | |||||
| </div> | ||||||
| </div> | ||||||
|
|
||||||
| <div className="md:w-2/5 bg-white/10 backdrop-blur-lg border border-white/10 rounded shadow-xl p-5 flex flex-col"> | ||||||
| <h3 className="text-lg font-semibold text-violet-300 mb-3" id="compiler-output-label"> | ||||||
| <div className="flex flex-col rounded border border-white/10 bg-white/10 p-5 shadow-xl backdrop-blur-lg md:w-2/5"> | ||||||
| <h3 className="mb-3 text-lg font-semibold text-violet-300" id="compiler-output-label"> | ||||||
| Output | ||||||
| </h3> | ||||||
| <pre | ||||||
| role="status" | ||||||
| aria-live="polite" | ||||||
| aria-labelledby="compiler-output-label" | ||||||
| className="bg-black/60 text-white rounded-xl p-4 h-[300px] md:h-[400px] overflow-y-auto text-sm font-mono whitespace-pre-wrap" | ||||||
| className="h-[300px] overflow-y-auto whitespace-pre-wrap rounded-xl bg-black/60 p-4 font-mono text-sm text-white md:h-[400px]" | ||||||
| > | ||||||
| {output} | ||||||
| </pre> | ||||||
| </div> | ||||||
| </div> | ||||||
|
|
||||||
| <div className="mx-auto max-w-6xl"> | ||||||
| <ComplexityProfiler | ||||||
| analysis={complexity} | ||||||
| supported={language === "63" || language === "74"} | ||||||
| /> | ||||||
| </div> | ||||||
| </div> | ||||||
| </> | ||||||
| ); | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import React from "react"; | ||
|
|
||
| const ComplexityProfiler = ({ analysis, supported = true }) => { | ||
| if (!supported) { | ||
| return ( | ||
| <section className="mt-4 rounded-xl border border-white/10 bg-white/5 p-4" aria-label="Complexity analysis"> | ||
| <div className="flex items-center justify-between gap-3"> | ||
| <h3 className="text-lg font-semibold text-violet-300">Complexity Analysis</h3> | ||
| <span className="rounded-full bg-gray-700 px-3 py-1 text-xs text-gray-300">JavaScript / TypeScript only</span> | ||
| </div> | ||
| <p className="mt-2 text-sm text-gray-300"> | ||
| AST analysis is currently available for JavaScript and TypeScript. Run or edit Java, Python, or C++ code normally. | ||
| </p> | ||
| </section> | ||
| ); | ||
| } | ||
|
|
||
| const isError = analysis?.status === "error"; | ||
| const isEmpty = analysis?.status === "empty"; | ||
|
|
||
| return ( | ||
| <section className="mt-4 rounded-xl border border-violet-400/20 bg-violet-500/5 p-4" aria-label="Complexity analysis"> | ||
| <div className="flex items-center justify-between gap-3"> | ||
| <h3 className="text-lg font-semibold text-violet-300">Complexity Analysis</h3> | ||
| <span className="rounded-full bg-violet-500/10 px-3 py-1 text-xs text-violet-200"> | ||
| AST heuristic | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2"> | ||
| <div className="rounded-lg border border-white/10 bg-black/20 p-3"> | ||
| <p className="text-xs uppercase tracking-wide text-gray-400">Time Complexity</p> | ||
| <p className="mt-1 text-2xl font-bold text-white">{analysis?.timeComplexity || "—"}</p> | ||
| </div> | ||
| <div className="rounded-lg border border-white/10 bg-black/20 p-3"> | ||
| <p className="text-xs uppercase tracking-wide text-gray-400">Space Complexity</p> | ||
| <p className="mt-1 text-2xl font-bold text-white">{analysis?.spaceComplexity || "—"}</p> | ||
| </div> | ||
| </div> | ||
|
|
||
| {analysis?.metrics && !isError && !isEmpty && ( | ||
| <div className="mt-3 flex flex-wrap gap-2 text-xs text-gray-300"> | ||
| <span className="rounded-full bg-white/10 px-3 py-1">Loops: {analysis.metrics.loopCount}</span> | ||
| <span className="rounded-full bg-white/10 px-3 py-1">Max nesting: {analysis.metrics.maxLoopDepth}</span> | ||
| <span className="rounded-full bg-white/10 px-3 py-1">Recursive calls: {analysis.metrics.recursiveCalls}</span> | ||
| </div> | ||
| )} | ||
|
|
||
| <p className="mt-3 text-sm text-gray-300">{analysis?.explanation}</p> | ||
|
|
||
| {analysis?.warnings?.length > 0 && ( | ||
| <ul className="mt-3 space-y-2" aria-label="Complexity warnings"> | ||
| {analysis.warnings.map((warning, index) => ( | ||
| <li key={`${warning}-${index}`} className="rounded-lg bg-amber-500/10 px-3 py-2 text-sm text-amber-200"> | ||
| {warning} | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| )} | ||
|
|
||
| {isError && ( | ||
| <p className="mt-3 text-xs text-gray-400">Fix the syntax error above and the profiler will analyze the code automatically.</p> | ||
| )} | ||
| </section> | ||
| ); | ||
| }; | ||
|
|
||
| export default ComplexityProfiler; |
Uh oh!
There was an error while loading. Please reload this page.