From 4d8bf68a0066185c5943cb7d4bc068a2e8d53ff0 Mon Sep 17 00:00:00 2001 From: leowjli Date: Fri, 22 Nov 2024 10:23:15 -0800 Subject: [PATCH 1/4] updated prompt and commented in app.ts --- src/app.ts | 1 + src/prompts.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/app.ts b/src/app.ts index 450ae71..aaf16a9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,6 +9,7 @@ import { processPullRequest } from "./review-agent"; import { applyReview } from "./reviews"; // This creates a new instance of the Octokit App class. +// This is a sample app const reviewApp = new App({ appId: env.GITHUB_APP_ID, privateKey: env.GITHUB_PRIVATE_KEY, diff --git a/src/prompts.ts b/src/prompts.ts index 42a907e..35dbd65 100644 --- a/src/prompts.ts +++ b/src/prompts.ts @@ -41,6 +41,7 @@ The review should focus on new code added in the PR (lines starting with '+'), a - ONLY PROVIDE CODE SUGGESTIONS - Focus on important suggestions like fixing code problems, improving performance, improving security, improving readability +- Specifically, could make suggestions on function modulization or code logic on top of performance, readability, and security - Avoid making suggestions that have already been implemented in the PR code. For example, if you want to add logs, or change a variable to const, or anything else, make sure it isn't already in the PR code. - Don't suggest adding docstring, type hints, or comments. - Suggestions should focus on improving the new code added in the PR (lines starting with '+') From 67b96111f51ab37e1c19481df0b4f1ceccd290ad Mon Sep 17 00:00:00 2001 From: leowjli Date: Fri, 22 Nov 2024 11:02:43 -0800 Subject: [PATCH 2/4] testing agent --- src/app.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app.ts b/src/app.ts index aaf16a9..543ac64 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,6 +10,7 @@ import { applyReview } from "./reviews"; // This creates a new instance of the Octokit App class. // This is a sample app +// testing const reviewApp = new App({ appId: env.GITHUB_APP_ID, privateKey: env.GITHUB_PRIVATE_KEY, From 9701a57986b1b8859ab6ac089d812c8f3eab9259 Mon Sep 17 00:00:00 2001 From: leowjli Date: Fri, 22 Nov 2024 11:10:31 -0800 Subject: [PATCH 3/4] testing the agent pt2 --- src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 543ac64..2d63eae 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,7 +10,7 @@ import { applyReview } from "./reviews"; // This creates a new instance of the Octokit App class. // This is a sample app -// testing +// testing part 2 const reviewApp = new App({ appId: env.GITHUB_APP_ID, privateKey: env.GITHUB_PRIVATE_KEY, From e6f2b824ee4d1a47a4461e3155456887badb3070 Mon Sep 17 00:00:00 2001 From: leowjli Date: Sat, 23 Nov 2024 20:57:17 -0800 Subject: [PATCH 4/4] added python parser --- package-lock.json | 75 ++++++++++++++++++++++++ package.json | 3 + src/context/language/python-parser.ts | 84 +++++++++++++++++++++++++-- 3 files changed, 158 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f60579a..f35c9c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,9 @@ "gpt-tokenizer": "^2.1.2", "groq-sdk": "^0.8.0", "octokit": "^3.1.1", + "python-ast": "^0.1.0", + "python-parser": "^1.0.3", + "python-shell": "^5.0.0", "xml2js": "^0.6.2" }, "devDependencies": { @@ -1157,6 +1160,21 @@ "node": ">=4" } }, + "node_modules/antlr4": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=16" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "license": "BSD-3-Clause" + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -1911,6 +1929,32 @@ "wrappy": "1" } }, + "node_modules/python-ast": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/python-ast/-/python-ast-0.1.0.tgz", + "integrity": "sha512-uMPE7HRMfsbHtQYPg/+EH9MJkynLfLr+0VJbeBgJHpt2wuDgf5hZrEczOIGNFKaO0W1HWiL7bSxA/EOOo70mIQ==", + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.3" + } + }, + "node_modules/python-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/python-parser/-/python-parser-1.0.3.tgz", + "integrity": "sha512-CjNc09lZr5ezmcW7J2r93Olk+hhAMIr/W2i8wugYj4gpaVly0rf4iEmSapk9CMZDzQAgWmQVzq/W15A+EWN2WA==", + "dependencies": { + "antlr4": "4.13.1" + } + }, + "node_modules/python-shell": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/python-shell/-/python-shell-5.0.0.tgz", + "integrity": "sha512-RUOOOjHLhgR1MIQrCtnEqz/HJ1RMZBIN+REnpSUrfft2bXqXy69fwJASVziWExfFXsR1bCY0TznnHooNsCo0/w==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", @@ -2959,6 +3003,16 @@ "color-convert": "^1.9.0" } }, + "antlr4": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==" + }, + "antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3541,6 +3595,27 @@ "wrappy": "1" } }, + "python-ast": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/python-ast/-/python-ast-0.1.0.tgz", + "integrity": "sha512-uMPE7HRMfsbHtQYPg/+EH9MJkynLfLr+0VJbeBgJHpt2wuDgf5hZrEczOIGNFKaO0W1HWiL7bSxA/EOOo70mIQ==", + "requires": { + "antlr4ts": "^0.5.0-alpha.3" + } + }, + "python-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/python-parser/-/python-parser-1.0.3.tgz", + "integrity": "sha512-CjNc09lZr5ezmcW7J2r93Olk+hhAMIr/W2i8wugYj4gpaVly0rf4iEmSapk9CMZDzQAgWmQVzq/W15A+EWN2WA==", + "requires": { + "antlr4": "4.13.1" + } + }, + "python-shell": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/python-shell/-/python-shell-5.0.0.tgz", + "integrity": "sha512-RUOOOjHLhgR1MIQrCtnEqz/HJ1RMZBIN+REnpSUrfft2bXqXy69fwJASVziWExfFXsR1bCY0TznnHooNsCo0/w==" + }, "qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", diff --git a/package.json b/package.json index fb08515..0d27701 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,9 @@ "gpt-tokenizer": "^2.1.2", "groq-sdk": "^0.8.0", "octokit": "^3.1.1", + "python-ast": "^0.1.0", + "python-parser": "^1.0.3", + "python-shell": "^5.0.0", "xml2js": "^0.6.2" }, "devDependencies": { diff --git a/src/context/language/python-parser.ts b/src/context/language/python-parser.ts index 845e90b..80884e7 100644 --- a/src/context/language/python-parser.ts +++ b/src/context/language/python-parser.ts @@ -1,15 +1,91 @@ import { AbstractParser, EnclosingContext } from "../../constants"; +import * as parser from 'python-ast'; + +interface Node { + type: string; + start: number; + end: number; + children: Node[]; +} + +// Helper function to convert a ParseTree to a Node +const parseTreeToNode = (parseTree: any): Node => { + return { + type: parseTree.type, + start: parseTree.start, + end: parseTree.end, + children: parseTree.children ? parseTree.children.map(parseTreeToNode) : [], + }; +}; + +const processNode = ( + node: Node, + lineStart: number, + lineEnd: number, + largestSize: number, + largestEnclosingContext: Node | null +) => { + // determining start and end line number + const start = node.start; + const end = start + (node.end - start); + + if (node.start <= lineStart && lineEnd <= node.end) { + const size = node.end - node.start; + if (size > largestSize) { + largestSize = size; + largestEnclosingContext = node; + } + } + return { largestSize, largestEnclosingContext }; +} + export class PythonParser implements AbstractParser { findEnclosingContext( file: string, lineStart: number, lineEnd: number ): EnclosingContext { - // TODO: Implement this method for Python - return null; + // parse the file as a parseTree + const ast = parser.parse(file); + // Convert ParseTree to Node + const rootNode = parseTreeToNode(ast); + let largestEnclosingContext: Node | null = null; + let largestSize = 0; + const traverseAST = (node: Node) => { + // check if the node is a current function or a class + if (node.type === 'FunctionDef' || node.type === 'ClassDef') { + ({ largestSize, largestEnclosingContext } = processNode( + node, + lineStart, + lineEnd, + largestSize, + largestEnclosingContext + )); + } + + // Traverse the children nodes + node.children.forEach((child) => traverseAST(child)); + }; + + traverseAST(rootNode); + return { + enclosingContext: largestEnclosingContext, + } as EnclosingContext; } dryRun(file: string): { valid: boolean; error: string } { - // TODO: Implement this method for Python - return { valid: false, error: "Not implemented yet" }; + try { + // tries to parse the Python code here + const ast = parser.parse(file); + const rootNode = parseTreeToNode(ast); + return { + valid: true, + error: "", + }; + } catch (err) { + return { + valid: false, + error: err.message, + }; + } } }