Skip to content
Open
Show file tree
Hide file tree
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
73 changes: 73 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assignLineNumbers = exports.getParserForExtension = exports.processGitFilepath = exports.sleep = void 0;
var javascript_parser_1 = require("./context/language/javascript-parser");
var sleep = function (ms) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })];
});
}); };
exports.sleep = sleep;
var processGitFilepath = function (filepath) {
// Remove the leading '/' if it exists
return filepath.startsWith("/") ? filepath.slice(1) : filepath;
};
exports.processGitFilepath = processGitFilepath;
var EXTENSIONS_TO_PARSERS = new Map([
["ts", new javascript_parser_1.JavascriptParser()],
["tsx", new javascript_parser_1.JavascriptParser()],
["js", new javascript_parser_1.JavascriptParser()],
["jsx", new javascript_parser_1.JavascriptParser()],
]);
var getParserForExtension = function (filename) {
var fileExtension = filename.split(".").pop().toLowerCase();
return EXTENSIONS_TO_PARSERS.get(fileExtension) || null;
};
exports.getParserForExtension = getParserForExtension;
var assignLineNumbers = function (contents) {
var lines = contents.split("\n");
var lineNumber = 1;
var linesWithNumbers = lines.map(function (line) {
var numberedLine = "".concat(lineNumber, ": ").concat(line);
lineNumber++;
return numberedLine;
});
return linesWithNumbers.join("\n");
};
exports.assignLineNumbers = assignLineNumbers;
5 changes: 4 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ export const processGitFilepath = (filepath: string) => {
return filepath.startsWith("/") ? filepath.slice(1) : filepath;
};

// Updated EnclosingContext interface
export interface EnclosingContext {
enclosingContext: Node | null;
enclosingContext: Node | null; // Existing property
type: "function" | "class"; // Added property
name: string; // Added property
}

export interface AbstractParser {
Expand Down
61 changes: 61 additions & 0 deletions src/context/language/javascript-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JavascriptParser = void 0;
var parser = require("@babel/parser");
var traverse_1 = require("@babel/traverse");
var processNode = function (path, lineStart, lineEnd, largestSize, largestEnclosingContext) {
var _a = path.node.loc, start = _a.start, end = _a.end;
if (start.line <= lineStart && lineEnd <= end.line) {
var size = end.line - start.line;
if (size > largestSize) {
largestSize = size;
largestEnclosingContext = path.node;
}
}
return { largestSize: largestSize, largestEnclosingContext: largestEnclosingContext };
};
var JavascriptParser = /** @class */ (function () {
function JavascriptParser() {
}
JavascriptParser.prototype.findEnclosingContext = function (file, lineStart, lineEnd) {
var ast = parser.parse(file, {
sourceType: "module",
plugins: ["jsx", "typescript"], // To allow JSX and TypeScript
});
var largestEnclosingContext = null;
var largestSize = 0;
(0, traverse_1.default)(ast, {
Function: function (path) {
var _a;
(_a = processNode(path, lineStart, lineEnd, largestSize, largestEnclosingContext), largestSize = _a.largestSize, largestEnclosingContext = _a.largestEnclosingContext);
},
TSInterfaceDeclaration: function (path) {
var _a;
(_a = processNode(path, lineStart, lineEnd, largestSize, largestEnclosingContext), largestSize = _a.largestSize, largestEnclosingContext = _a.largestEnclosingContext);
},
});
return {
enclosingContext: largestEnclosingContext,
};
};
JavascriptParser.prototype.dryRun = function (file) {
try {
var ast = parser.parse(file, {
sourceType: "module",
plugins: ["jsx", "typescript"], // To allow JSX and TypeScript
});
return {
valid: true,
error: "",
};
}
catch (exc) {
return {
valid: false,
error: exc,
};
}
};
return JavascriptParser;
}());
exports.JavascriptParser = JavascriptParser;
62 changes: 62 additions & 0 deletions src/context/language/python-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PythonParser = void 0;
var PythonParser = /** @class */ (function () {
function PythonParser() {
}
/**
* Finds the enclosing context (function or class) of a given line range.
* @param file - The Python file content as a string.
* @param lineStart - The starting line number.
* @param lineEnd - The ending line number.
* @returns The enclosing context, or null if not found.
*/
PythonParser.prototype.findEnclosingContext = function (file, lineStart, lineEnd) {
var lines = file.split("\n");
var context = null;
// Search upwards from the starting line to find the enclosing context
for (var i = lineStart - 1; i >= 0; i--) {
var line = lines[i].trim();
if (line.startsWith("def ")) {
context = {
type: "function",
name: line.split(" ")[1].split("(")[0], // Extract function name
};
break;
}
else if (line.startsWith("class ")) {
context = {
type: "class",
name: line.split(" ")[1].split("(")[0], // Extract class name
};
break;
}
}
return context; // Returns null if no context is found
};
/**
* Performs a dry run to check if the Python file is valid syntax.
* @param file - The Python file content as a string.
* @returns An object indicating validity and any error message.
*/
PythonParser.prototype.dryRun = function (file) {
try {
var spawnSync = require("child_process").spawnSync;
var result = spawnSync("python3", ["-m", "py_compile", "-"], {
input: file,
encoding: "utf-8",
});
if (result.status === 0) {
return { valid: true, error: "" }; // File is valid
}
else {
return { valid: false, error: result.stderr.toString() }; // Syntax error
}
}
catch (e) {
return { valid: false, error: e.message }; // Handle unexpected errors
}
};
return PythonParser;
}());
exports.PythonParser = PythonParser;
55 changes: 51 additions & 4 deletions src/context/language/python-parser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,62 @@
import { AbstractParser, EnclosingContext } from "../../constants";

export class PythonParser implements AbstractParser {
/**
* Finds the enclosing context (function or class) of a given line range.
* @param file - The Python file content as a string.
* @param lineStart - The starting line number.
* @param lineEnd - The ending line number.
* @returns The enclosing context, or null if not found.
*/
findEnclosingContext(
file: string,
lineStart: number,
lineEnd: number
): EnclosingContext {
// TODO: Implement this method for Python
return null;
const lines = file.split("\n");
let context: EnclosingContext = null;

// Search upwards from the starting line to find the enclosing context
for (let i = lineStart - 1; i >= 0; i--) {
const line = lines[i].trim();
if (line.startsWith("def ")) {
context = {
type: "function",
name: line.split(" ")[1].split("(")[0], // Extract function name
};
break;
} else if (line.startsWith("class ")) {
context = {
type: "class",
name: line.split(" ")[1].split("(")[0], // Extract class name
};
break;
}
}

return context; // Returns null if no context is found
}

/**
* Performs a dry run to check if the Python file is valid syntax.
* @param file - The Python file content as a string.
* @returns An object indicating validity and any error message.
*/
dryRun(file: string): { valid: boolean; error: string } {
// TODO: Implement this method for Python
return { valid: false, error: "Not implemented yet" };
try {
const { spawnSync } = require("child_process");
const result = spawnSync("python3", ["-m", "py_compile", "-"], {
input: file, // Pass the file content to Python
encoding: "utf-8",
});

if (result.status === 0) {
return { valid: true, error: "" }; // File is valid
} else {
return { valid: false, error: result.stderr.toString() }; // Syntax error
}
} catch (e) {
return { valid: false, error: e.message }; // Handle unexpected errors
}
}
}