Skip to content

Commit

Permalink
build: added function list button to tools tab.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmiscool committed Dec 12, 2024
1 parent d009fd9 commit 8f458f0
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 65 deletions.
164 changes: 108 additions & 56 deletions public/toolsManager.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { doAjax } from "./doAjax.js";

import { doAjax } from './doAjax.js';
let ctx;

const buttonStyle = {
display: 'block',
margin: '5px',
padding: '5px',
borderRadius: '5px',
textAlign: 'center',
cursor: 'pointer',
}



cursor: 'pointer'
};
export class toolsManager {
constructor(container, app_ctx) {
ctx = app_ctx;
Expand All @@ -22,60 +18,53 @@ export class toolsManager {
this.container.style.flex = '1';
this.container.style.flexDirection = 'column';
this.container.style.overflow = 'auto';

this.snippetTextArea = null;

this.showToolBar();
}

async showToolBar() {
this.container.innerHTML = '';
this.toolBar = document.createElement('div');
this.toolBar.style.display = 'flex';
this.toolBar.style.flexDirection = 'row';
//toolBar.style.justifyContent = 'space-between';
// toolBar.style.justifyContent = 'space-between';
this.toolBar.style.margin = '0px';

const pullMethodsListButton = await this.makeToolBarButton('Methods List', async () => {
await this.pullMethodsList();
});
this.toolBar.appendChild(pullMethodsListButton);

const pullStubsListButton = await this.makeToolBarButton('Stubs List', async () => {
await this.pullMethodsList(true);
});
this.toolBar.appendChild(pullStubsListButton);

const pullFunctionListButton = await this.makeToolBarButton('Function List', async () => {
await this.pullFunctionList();
});
this.toolBar.appendChild(pullFunctionListButton);
const implementAllStubsButton = await this.makeToolBarButton('Implement All Stubs', async () => {
await this.implementAllStubs();
});
this.toolBar.appendChild(implementAllStubsButton);

// button to call the mergeAndFormat api endpoint
const mergeAndFormatButton = await this.makeToolBarButton('Merge and Format', async () => {
await this.mergeAndFormat();
});
this.toolBar.appendChild(mergeAndFormatButton);

// button to call the prependClassStructure api endpoint
const prependClassStructureButton = await this.makeToolBarButton('Prepend Class Structure', async () => {
await this.prependClassStructure();
});
this.toolBar.appendChild(prependClassStructureButton);



this.container.appendChild(this.toolBar);
}

async implementAllStubs() {
if (!await this.verifyTargetFileSpecified()) return;
if (!await this.verifyTargetFileSpecified())
return;
this.showToolBar();
await doAjax('/implementAllStubs', { targetFile: ctx.targetFile });
}

async mergeAndFormat() {
if (!await this.verifyTargetFileSpecified()) return;
if (!await this.verifyTargetFileSpecified())
return;
this.showToolBar();
let snippet = '';
if (this.snippetTextArea === null) {
Expand All @@ -92,14 +81,11 @@ export class toolsManager {
snippet = this.snippetTextArea.value;
this.snippetTextArea = null;
}


await doAjax('/applySnippet', {
targetFile: ctx.targetFile,
snippet: snippet,
snippet: snippet
});
}

async makeToolBarButton(title, handler) {
const button = document.createElement('button');
button.textContent = title;
Expand All @@ -108,72 +94,138 @@ export class toolsManager {
this.toolBar.appendChild(button);
return button;
}

async prependClassStructure() {
if (!await this.verifyTargetFileSpecified()) return;
if (!await this.verifyTargetFileSpecified())
return;
await doAjax('/prependClassStructure', { targetFile: ctx.targetFile });
}

async pullMethodsList(showOnlyStubs = false) {
this.showToolBar();
if (!await this.verifyTargetFileSpecified()) return;


if (!await this.verifyTargetFileSpecified())
return;
const listOfMethods = await doAjax('/getMethodsList', { targetFile: ctx.targetFile });
// the response contains
console.log(listOfMethods);
// the response contains
for (const className in listOfMethods) {
//console.log(className);
// console.log(className);
const methods = listOfMethods[className];

for (const { name, args, isStub, lineNumber } of methods) {
if (showOnlyStubs && !isStub) continue;

for (const {name, args, isStub, lineNumber} of methods) {
if (showOnlyStubs && !isStub)
continue;
const argList = args.join(', ');

console.log(`${className}.${name}(${argList})`);

console.log(`${ className }.${ name }(${ argList })`);
const methodItemElement = document.createElement('dim');
// add class .hover-effect to
methodItemElement.classList.add('hover-effect');

methodItemElement.textContent = `${className}.${name}(${argList})`;
methodItemElement.textContent = `${ className }.${ name }(${ argList })`;
if (isStub) {
methodItemElement.style.color = 'red';
methodItemElement.addEventListener('click', async () => {
await this.implementSpecificClassMethod(className, name, lineNumber);
await this.pullMethodsList(showOnlyStubs);
});
}
else {
} else {
methodItemElement.style.color = 'green';
methodItemElement.addEventListener('click', async () => {
await this.addToChatPrompt(className, name, lineNumber);
console.log('this is the line number ', lineNumber);
await this.pullMethodsList(showOnlyStubs);
});
}

this.container.appendChild(methodItemElement);
this.container.appendChild(document.createElement('br'));
}
}
}

async pullFunctionList(showOnlyStubs = false) {
// this calls the getFunctionList endpoint and displays the list of functions in the container
// similar to pullMethodsList, but for functions
this.showToolBar();
if (!await this.verifyTargetFileSpecified())
return;
const listOfFunctions = await doAjax('/getFunctionList', { targetFile: ctx.targetFile });
console.log(listOfFunctions);
/* format of the response
{
"test": {
"functionName": "test",
"args": [],
"isStub": true,
"lineNumber": 1131
},
"test2": {
"functionName": "test2",
"args": [],
"isStub": true,
"lineNumber": 1135
}
}*/
for (const key in listOfFunctions) {
console.log(key);
// Logs the key (function name) from the response
const {functionName, args, isStub, lineNumber} = listOfFunctions[key];
const argList = args.join(', ');
console.log(`${ functionName }(${ argList })`);
const functionItemElement = document.createElement('dim');
// add class .hover-effect to
functionItemElement.classList.add('hover-effect');
functionItemElement.textContent = `${ functionName }(${ argList })`;
if (isStub) {
functionItemElement.style.color = 'red';
functionItemElement.addEventListener('click', async () => {
await this.implementSpecificFunction(functionName, lineNumber);
await this.pullFunctionList(showOnlyStubs);
});
} else {
functionItemElement.style.color = 'green';
functionItemElement.addEventListener('click', async () => {
await this.addFunctionToChatPrompt(functionName, lineNumber);
console.log('this is the line number ', lineNumber);
await this.pullFunctionList(showOnlyStubs);
});
}
this.container.appendChild(functionItemElement);
this.container.appendChild(document.createElement('br'));
}
}
async implementSpecificClassMethod(className, methodName, lineNumber) {
ctx.tabs.switchToTab('Chat');
await doAjax('/gotoLineNumber', { lineNumber, targetFile: ctx.targetFile });
await ctx.chat.newChat(`Implement ${methodName}.${className}`);
await ctx.chat.addMessage(`Write the ${methodName} method in the ${className} class.`);
await doAjax('/gotoLineNumber', {
lineNumber,
targetFile: ctx.targetFile
});
await ctx.chat.newChat(`Implement ${ methodName }.${ className }`);
await ctx.chat.addMessage(`Write the ${ methodName } method in the ${ className } class.`);
await ctx.chat.callLLM();
}

async addToChatPrompt(className, methodName, lineNumber) {
ctx.tabs.switchToTab('Chat');
await doAjax('/gotoLineNumber', { lineNumber, targetFile: ctx.targetFile });
await ctx.chat.newChat(`Modify ${methodName}.${className}`);
await ctx.chat.setInput(`Modify the ${methodName} method in the ${className} class.\nImprove it.`);
await doAjax('/gotoLineNumber', {
lineNumber,
targetFile: ctx.targetFile
});
await ctx.chat.newChat(`Modify ${ methodName }.${ className }`);
await ctx.chat.setInput(`Modify the ${ methodName } method in the ${ className } class.\nImprove it.`);
}
async implementSpecificFunction(functionName, lineNumber) {
ctx.tabs.switchToTab('Chat');
await doAjax('/gotoLineNumber', {
lineNumber,
targetFile: ctx.targetFile
});
await ctx.chat.newChat(`Implement ${ functionName }`);
await ctx.chat.addMessage(`Write the ${ functionName } function.`);
await ctx.chat.callLLM();
}
async addFunctionToChatPrompt(functionName, lineNumber) {
ctx.tabs.switchToTab('Chat');
await doAjax('/gotoLineNumber', {
lineNumber,
targetFile: ctx.targetFile
});
await ctx.chat.newChat(`Modify ${ functionName }`);
await ctx.chat.setInput(`Modify the ${ functionName } function.\nImprove it.`);
}

async verifyTargetFileSpecified() {
if (!ctx.targetFile) {
alert('Please select a file first');
Expand Down
9 changes: 6 additions & 3 deletions src/aiCoderApiFunctions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { applySnippets } from "./intelligentMerge.js"
import { getMethodsWithArguments } from "./classListing.js";
import { getListOfFunctions, getMethodsWithArguments } from "./classListing.js";
import { appendFile, getAllFiles, readFile, readOrLoadFromDefault, writeFile } from "./fileIO.js";
import { intelligentlyMergeSnippets } from "./intelligentMerge.js";
import { llmSettings, llmSettingsUpdate } from "./llmCall.js";
Expand Down Expand Up @@ -98,9 +98,12 @@ export class aiCoderApiFunctions {
}

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

async getFunctionList(parsedBody) {
const response = await getListOfFunctions(await readFile(parsedBody.targetFile));
return response;
}

Expand Down
23 changes: 17 additions & 6 deletions src/classListing.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
const classInfo = new Map();

ast.body.forEach(node => {
console.log(node);
let classNode = null;

if (node.type === 'ClassDeclaration') {
Expand All @@ -70,8 +69,11 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
let methods = [];

classNode.body.body.forEach(classElement => {

if (classElement.type === 'MethodDefinition' && classElement.key.type === 'Identifier') {
const methodName = classElement.key.name;
const lineNumber = classElement.loc.start.line;
console.log(methodName,lineNumber);

const args = classElement.value.params.map(param => {
if (param.type === 'Identifier') return param.name;
Expand All @@ -86,15 +88,15 @@ export function getMethodsWithArguments(code, onlyStubs = false) {
methodBody[0].type === 'ReturnStatement' &&
!methodBody[0].argument);

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

if (onlyStubs) {
methods = methods.filter(m => m.isStub);
}

classInfo.set(className, { className, parentClassName, methods });
classInfo.set(className, { className, parentClassName, methods});
}
});

Expand Down Expand Up @@ -152,7 +154,7 @@ export async function getListOfFunctions(code) {
loc: true,
attachComment: true,
});
const functionInfo = new Map();
const functionsInfo = new Map();

ast.body.forEach(node => {
let functionNode = null;
Expand All @@ -169,17 +171,26 @@ export async function getListOfFunctions(code) {

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

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);
});

functionInfo.set(functionName, { functionName, args });
const isStub = functionNode.body.body.length === 0;

functionsInfo.set(functionName, { functionName, args, isStub, lineNumber });
}
});

return functionInfo;
// convert the Map to an object
const result = {};
functionsInfo.forEach((value, key) => {
result[key] = value;
});

return result;
}

2 changes: 2 additions & 0 deletions src/prompts/snippet-production-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ class exampleClass {
}
```

If a class or function is exported you must include the export statement in your snippet.

**Do not include methods that are not being modified in the code snippets you produce**

0 comments on commit 8f458f0

Please sign in to comment.