From f9e9c4da0a71c3eeb9a84fa64158709d5328bcfd Mon Sep 17 00:00:00 2001 From: Amanuel Sisay Date: Mon, 25 Nov 2024 13:44:45 +0300 Subject: [PATCH] (feat): add java parser --- package-lock.json | 76 ++++++++++++++++++++++++++++ package.json | 3 ++ src/constants.ts | 4 ++ src/context/language/java-parser.ts | 78 +++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 src/context/language/java-parser.ts diff --git a/package-lock.json b/package-lock.json index f60579a..386ce5a 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", + "tree-sitter": "^0.21.1", + "tree-sitter-java": "^0.23.4", + "tree-sitter-python": "^0.23.4", "xml2js": "^0.6.2" }, "devDependencies": { @@ -2113,6 +2116,52 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/tree-sitter": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", + "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^8.0.0", + "node-gyp-build": "^4.8.0" + } + }, + "node_modules/tree-sitter-java": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-java/-/tree-sitter-java-0.23.4.tgz", + "integrity": "sha512-WmqZPzvaHpAcAdJBjwMFwusL+ahp2Liv6T0ASWU7sxGZGceSdP5MpW+2DwLNOiWld39C1WR+9qk99hk4qHK5vw==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-python": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.23.4.tgz", + "integrity": "sha512-MbmUAl7y5UCUWqHscHke7DdRDwQnVNMNKQYQc4Gq2p09j+fgPxaU8JVsuOI/0HD3BSEEe5k9j3xmdtIWbDtDgw==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^8.2.1", + "node-gyp-build": "^4.8.2" + }, + "peerDependencies": { + "tree-sitter": "^0.21.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, "node_modules/tsx": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", @@ -3687,6 +3736,33 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "tree-sitter": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", + "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", + "requires": { + "node-addon-api": "^8.0.0", + "node-gyp-build": "^4.8.0" + } + }, + "tree-sitter-java": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-java/-/tree-sitter-java-0.23.4.tgz", + "integrity": "sha512-WmqZPzvaHpAcAdJBjwMFwusL+ahp2Liv6T0ASWU7sxGZGceSdP5MpW+2DwLNOiWld39C1WR+9qk99hk4qHK5vw==", + "requires": { + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" + } + }, + "tree-sitter-python": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.23.4.tgz", + "integrity": "sha512-MbmUAl7y5UCUWqHscHke7DdRDwQnVNMNKQYQc4Gq2p09j+fgPxaU8JVsuOI/0HD3BSEEe5k9j3xmdtIWbDtDgw==", + "requires": { + "node-addon-api": "^8.2.1", + "node-gyp-build": "^4.8.2" + } + }, "tsx": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", diff --git a/package.json b/package.json index fb08515..21ed94f 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", + "tree-sitter": "^0.21.1", + "tree-sitter-java": "^0.23.4", + "tree-sitter-python": "^0.23.4", "xml2js": "^0.6.2" }, "devDependencies": { diff --git a/src/constants.ts b/src/constants.ts index 14c7de1..e617895 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,8 @@ import { Node } from "@babel/traverse"; import { JavascriptParser } from "./context/language/javascript-parser"; import { ChatCompletionMessageParam } from "groq-sdk/resources/chat/completions"; +import { PythonParser } from "./context/language/python-parser"; +import { JavaParser } from "./context/language/java-parser"; export interface PRFile { sha: string; @@ -107,6 +109,8 @@ const EXTENSIONS_TO_PARSERS: Map = new Map([ ["tsx", new JavascriptParser()], ["js", new JavascriptParser()], ["jsx", new JavascriptParser()], + ["py", new PythonParser()], + ["java", new JavaParser()], ]); export const getParserForExtension = (filename: string) => { diff --git a/src/context/language/java-parser.ts b/src/context/language/java-parser.ts new file mode 100644 index 0000000..6949262 --- /dev/null +++ b/src/context/language/java-parser.ts @@ -0,0 +1,78 @@ +import { AbstractParser, EnclosingContext } from "../../constants"; +import traverse, { NodePath, Node } from "@babel/traverse"; +import { SyntaxNode } from "tree-sitter"; + +const Parser = require("tree-sitter"); +const Java = require("tree-sitter-java"); + +const parser = new Parser(); +parser.setLanguage(Java); + +const processNode = ( + node: SyntaxNode, + lineStart: number, + lineEnd: number, + largestSize: number, + largestEnclosingContext: SyntaxNode | null +) => { + const start = node.startPosition; + const end = node.endPosition; + + if (start.row <= lineStart && lineEnd <= end.row) { + const size = end.row - start.row; + if (size > largestSize) { + largestSize = size; + largestEnclosingContext = node; + } + } + + return { largestSize, largestEnclosingContext }; +}; + +export class JavaParser implements AbstractParser { + findEnclosingContext( + file: string, + lineStart: number, + lineEnd: number + ): EnclosingContext { + const tree = parser.parse(file); + let largestEnclosingContext: SyntaxNode | null = null; + let largestSize = 0; + + const cursor = tree.walk(); + let first = true + while (first || cursor.gotoNextSibling() || cursor.gotoParent()) + { + const node = cursor.currentNode; + const node_types = ["method_declaration", "class_declaration", "compilation_unit"]; + if ( + node_types.includes(node.type) + ) { + ({ largestSize, largestEnclosingContext } = processNode( + node, + lineStart, + lineEnd, + largestSize, + largestEnclosingContext, + )); + } + first = false + } + return { enclosingContext: largestEnclosingContext } as EnclosingContext; + } + + dryRun(file: string): { valid: boolean; error: string } { + try { + const tree = parser.parse(file); + return { + valid: true, + error: "", + }; + } catch (exc) { + return { + valid: false, + error: exc, + }; + } + } +}