Skip to content

Commit

Permalink
build: Fixed problem where exported classes were not showing in metho…
Browse files Browse the repository at this point in the history
…ds list.
  • Loading branch information
mmiscool committed Dec 12, 2024
1 parent a588e78 commit 3b76afa
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 32 deletions.
1 change: 1 addition & 0 deletions public/ChatManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export class ChatManager {

async setTargetFile(targetFile) {
this.targetFileInput.value = targetFile;
ctx.targetFile = targetFile;
}

async loadConversationsList() {
Expand Down
28 changes: 28 additions & 0 deletions public/LLMSettingsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ export class LLMSettingsManager {
this.addRefreshButton();
this.llmSettings = await this.fetchSettings();
this.createSettingsDiv();
// check if there is an active LLM
const activeLLM = await this.getActiveLLM();
// if no LLMS are active swap to this tab
if (!activeLLM) {
await ctx.tabs.disableAllTabs();
await ctx.tabs.enableTab('LLM Settings');

// add an element to the top of the container to notify the user
const notification = document.createElement('div');
notification.textContent = 'You must select an active LLM and model';
notification.style.backgroundColor = 'red';
notification.style.color = 'white';
notification.style.padding = '10px';
notification.style.margin = '10px';
this.container.insertBefore(notification, this.settingsDiv);

}else{
ctx.tabs.enableAllTabs();
}
}

async addRefreshButton() {
Expand Down Expand Up @@ -128,6 +147,15 @@ export class LLMSettingsManager {
}
}

async getActiveLLM() {
for (const llmDiv of this.settingsDiv.children) {
if (llmDiv.querySelector('input[type="checkbox"]').checked) {
return llmDiv.querySelector('h2').textContent;
}
}
return null;
}

async saveSettings() {
const newSettings = {};
const activeModels = [];
Expand Down
2 changes: 1 addition & 1 deletion public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ async function setup() {
const llmSettingsTab = tabs.createTab("LLM Settings","🧠");
ctx.llmSettings = new LLMSettingsManager(llmSettingsTab, ctx);


document.body.style.margin = "0";
document.body.style.height = "100vh";
document.body.style.display = "flex";

document.body.appendChild(tabs.getElement());


window.ctx = ctx;
}

Expand Down
40 changes: 40 additions & 0 deletions public/tabInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,45 @@ export class tabInterface {
}
});
}

async disableTab(tabName) {
// make the tab not clickable and greyed out
const idx = this.tabs.findIndex(tab => tab.name.toLowerCase() === tabName.toLowerCase());
if (idx !== -1) {
this.tabBar.childNodes[idx].style.pointerEvents = "none";
this.tabBar.childNodes[idx].style.textDecoration = "line-through";
}
}

async enableTab(tabName) {
const idx = await this.tabs.findIndex(tab => tab.name.toLowerCase() === tabName.toLowerCase());

if (idx !== -1) {
this.tabBar.childNodes[idx].style.pointerEvents = "auto";
this.tabBar.childNodes[idx].style.backgroundColor = this.colors.tabButtonBackground;
this.tabBar.childNodes[idx].style.textDecoration = "none";
}
// set this tab as active
this.activeTab = idx;
return await this.showActiveTab();

}

async disableAllTabs() {
for (let i = 0; i < this.tabBar.childNodes.length; i++) {
this.tabBar.childNodes[i].style.pointerEvents = "none";
this.tabBar.childNodes[i].style.textDecoration = "line-through";
}
return true;
}

async enableAllTabs() {
for (let i = 0; i < this.tabBar.childNodes.length; i++) {
this.tabBar.childNodes[i].style.pointerEvents = "auto";
this.tabBar.childNodes[i].style.backgroundColor = this.colors.tabButtonBackground;
this.tabBar.childNodes[i].style.textDecoration = "none";
}
return true;
}
}

2 changes: 2 additions & 0 deletions src/aiCoderApiFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ export class aiCoderApiFunctions {
}

async getMethodsList(parsedBody) {
console.log(parsedBody);
const response = await getMethodsWithArguments(await readFile(parsedBody.targetFile));
console.log('getMethodsList', response);
return response;
}

Expand Down
70 changes: 39 additions & 31 deletions src/classListing.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { readFile, writeFile } from './fileIO.js';
import * as esprima from 'esprima';
import * as esprima from 'esprima-next';

export async function prependClassStructure(targetFile, onlyStubs = false) {
// You can toggle onlyStubs = true or false as needed
Expand Down Expand Up @@ -41,51 +41,55 @@ export async function prependClassStructure(targetFile, onlyStubs = false) {


export function getMethodsWithArguments(code, onlyStubs = false) {
//console.log(code);
// Parse the code using esprima
const ast = esprima.parseModule(code, {
sourceType: 'module',
tolerant: true,
range: true,
loc: true,
attachComment: true
attachComment: true,
});
const classInfo = new Map();

// Collect information on each class, its methods, and arguments
ast.body.forEach(node => {
if (node.type === 'ClassDeclaration' && node.id && node.id.name) {
const className = node.id.name;
const parentClassName = node.superClass && node.superClass.name ? node.superClass.name : null;
console.log(node);
let classNode = null;

if (node.type === 'ClassDeclaration') {
classNode = node;
} else if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
node.declaration.type === 'ClassDeclaration'
) {
classNode = node.declaration;
}

if (classNode && classNode.id && classNode.id.name) {
const className = classNode.id.name;
const parentClassName = classNode.superClass && classNode.superClass.name ? classNode.superClass.name : null;
let methods = [];

node.body.body.forEach(classElement => {
classNode.body.body.forEach(classElement => {
if (classElement.type === 'MethodDefinition' && classElement.key.type === 'Identifier') {
const methodName = classElement.key.name;
const startCharacterLocation = classElement.start;
//console.log(classElement.loc);
const lineNumber = classElement.loc.start.line;

// Collect method arguments
const args = classElement.value.params.map(param => {
if (param.type === 'Identifier') return param.name;
if (param.type === 'AssignmentPattern' && param.left.type === 'Identifier') return param.left.name;
return 'unknown';
});

// Check if method is a stub
const methodBody = classElement.value.body?.body || [];
const isStub =
methodBody.length === 0 ||
(methodBody.length === 1 &&
methodBody[0].type === 'ReturnStatement' &&
!methodBody[0].argument);

methods.push({ name: methodName, args, isStub, lineNumber });
methods.push({ name: methodName, args, isStub });
}
});

// If onlyStubs is true, filter out non-stub methods
if (onlyStubs) {
methods = methods.filter(m => m.isStub);
}
Expand All @@ -94,7 +98,6 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
}
});

// Sort classes based on dependency hierarchy
const sortedClasses = [];
const processedClasses = new Set();

Expand All @@ -103,7 +106,6 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
const classData = classInfo.get(className);
if (!classData) return;

// Add the parent class first if it exists
if (classData.parentClassName && classInfo.has(classData.parentClassName)) {
addClassAndSubclasses(classData.parentClassName);
}
Expand All @@ -112,18 +114,13 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
processedClasses.add(className);
}

//console.log(classInfo);
// Process classes in the order they appear in the original code
Array.from(classInfo.keys()).forEach(addClassAndSubclasses);

// Convert sorted classes into the final output format
const result = {};
sortedClasses.forEach(({ className, methods }) => {
result[className] = methods;
});



return result;
}

Expand All @@ -147,24 +144,34 @@ export async function getStubMethods(code) {
}


export async function getListOfFunctions(code){
// we are getting the functions in the application. Not the classes or class methods
export async function getListOfFunctions(code) {
const ast = esprima.parseModule(code, {
sourceType: 'module',
tolerant: true,
range: true,
loc: true,
attachComment: true
attachComment: true,
});
const functionInfo = new Map();

// Collect information on each function, its arguments
ast.body.forEach(node => {
if (node.type === 'FunctionDeclaration' && node.id && node.id.name) {
const functionName = node.id.name;
let functionNode = null;

if (node.type === 'FunctionDeclaration') {
functionNode = node;
} else if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
node.declaration.type === 'FunctionDeclaration'
) {
functionNode = node.declaration;
}

if (functionNode && functionNode.id && functionNode.id.name) {
const functionName = functionNode.id.name;
let args = [];

node.params.forEach(param => {
functionNode.params.forEach(param => {
if (param.type === 'Identifier') args.push(param.name);
if (param.type === 'AssignmentPattern' && param.left.type === 'Identifier') args.push(param.left.name);
});
Expand All @@ -174,4 +181,5 @@ export async function getListOfFunctions(code){
});

return functionInfo;
}
}

0 comments on commit 3b76afa

Please sign in to comment.