@jpoly1219/context-extractor 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/app.d.ts +27 -0
- package/dist/app.js +284 -0
- package/dist/codeql.d.ts +17 -0
- package/dist/codeql.js +1341 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.js +62 -0
- package/dist/core.d.ts +20 -0
- package/dist/core.js +576 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/main.d.ts +13 -0
- package/dist/main.js +254 -0
- package/dist/ocaml-driver.d.ts +30 -0
- package/dist/ocaml-driver.js +394 -0
- package/dist/ocaml-type-checker.d.ts +52 -0
- package/dist/ocaml-type-checker.js +286 -0
- package/dist/runner.d.ts +1 -0
- package/dist/runner.js +52 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.js +14 -0
- package/dist/typescript-driver.d.ts +27 -0
- package/dist/typescript-driver.js +542 -0
- package/dist/typescript-type-checker.d.ts +64 -0
- package/dist/typescript-type-checker.js +512 -0
- package/dist/utils.d.ts +40 -0
- package/dist/utils.js +350 -0
- package/package.json +1 -1
package/dist/app.d.ts
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Language, Context } from "./types";
|
2
|
+
export declare class App {
|
3
|
+
private language;
|
4
|
+
private languageDriver;
|
5
|
+
private languageServer;
|
6
|
+
private lspClient;
|
7
|
+
private sketchPath;
|
8
|
+
private repoPath;
|
9
|
+
private result;
|
10
|
+
private timeout;
|
11
|
+
constructor(language: Language, sketchPath: string, repoPath: string);
|
12
|
+
init(): Promise<void>;
|
13
|
+
run(): Promise<void>;
|
14
|
+
close(): void;
|
15
|
+
getSavedResult(): Context | null;
|
16
|
+
}
|
17
|
+
export declare class CompletionEngine {
|
18
|
+
private language;
|
19
|
+
private config;
|
20
|
+
private sketchPath;
|
21
|
+
constructor(language: Language, sketchPath: string, configPath: string);
|
22
|
+
completeWithLLM(context: Context): Promise<string>;
|
23
|
+
generateTypesAndHeadersPrompt(sketchFileContent: string, holeType: string, relevantTypes: string, relevantHeaders: string): {
|
24
|
+
role: string;
|
25
|
+
content: string;
|
26
|
+
}[];
|
27
|
+
}
|
package/dist/app.js
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
exports.CompletionEngine = exports.App = void 0;
|
30
|
+
const path = __importStar(require("path"));
|
31
|
+
const fs = __importStar(require("fs"));
|
32
|
+
const child_process_1 = require("child_process");
|
33
|
+
const child_process_2 = require("child_process");
|
34
|
+
const openai_1 = __importDefault(require("openai"));
|
35
|
+
const main_1 = require("../ts-lsp-client-dist/src/main");
|
36
|
+
const types_1 = require("./types");
|
37
|
+
// TODO: Bundle the drivers as barrel exports.
|
38
|
+
const typescript_driver_1 = require("./typescript-driver");
|
39
|
+
const ocaml_driver_1 = require("./ocaml-driver");
|
40
|
+
const utils_1 = require("./utils");
|
41
|
+
class App {
|
42
|
+
constructor(language, sketchPath, repoPath) {
|
43
|
+
// private result: {
|
44
|
+
// hole: string;
|
45
|
+
// relevantTypes: string[];
|
46
|
+
// relevantHeaders: string[];
|
47
|
+
// } | null = null;
|
48
|
+
this.result = null;
|
49
|
+
// Optional timeout for forced termination
|
50
|
+
this.timeout = setTimeout(() => {
|
51
|
+
if (!this.languageServer.killed) {
|
52
|
+
console.log('Forcibly killing the process...');
|
53
|
+
this.languageServer.kill('SIGKILL');
|
54
|
+
}
|
55
|
+
}, 5000);
|
56
|
+
this.language = language;
|
57
|
+
this.sketchPath = sketchPath;
|
58
|
+
this.repoPath = repoPath;
|
59
|
+
const r = (() => {
|
60
|
+
switch (language) {
|
61
|
+
case types_1.Language.TypeScript: {
|
62
|
+
this.languageDriver = new typescript_driver_1.TypeScriptDriver();
|
63
|
+
return (0, child_process_1.spawn)("typescript-language-server", ["--stdio"], { stdio: ["pipe", "pipe", "pipe"] });
|
64
|
+
}
|
65
|
+
case types_1.Language.OCaml: {
|
66
|
+
this.languageDriver = new ocaml_driver_1.OcamlDriver();
|
67
|
+
try {
|
68
|
+
(0, child_process_2.execSync)(`eval $(opam env --switch=. --set-switch)`, { shell: "/bin/bash" });
|
69
|
+
// execSync("opam switch .", { shell: "/bin/bash" })
|
70
|
+
const currDir = __dirname;
|
71
|
+
process.chdir(path.dirname(sketchPath));
|
72
|
+
// execSync("which dune", { shell: "/bin/bash" })
|
73
|
+
(0, child_process_1.spawn)("dune", ["build", "-w"]);
|
74
|
+
process.chdir(currDir);
|
75
|
+
}
|
76
|
+
catch (err) {
|
77
|
+
console.log("ERROR:", err);
|
78
|
+
}
|
79
|
+
// TODO: Spawn a dune build -w on sketch directory.
|
80
|
+
// try {
|
81
|
+
// execSync("which dune", { shell: "/bin/bash" })
|
82
|
+
// spawn("dune", ["build", "-w"]);
|
83
|
+
// } catch (err) {
|
84
|
+
// console.log("ERROR:", err)
|
85
|
+
// }
|
86
|
+
// process.chdir(currDir);
|
87
|
+
return (0, child_process_1.spawn)("ocamllsp", ["--stdio"]);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
})();
|
91
|
+
const e = new main_1.JSONRPCEndpoint(r.stdin, r.stdout);
|
92
|
+
const c = new main_1.LspClient(e);
|
93
|
+
this.languageServer = r;
|
94
|
+
this.lspClient = c;
|
95
|
+
this.languageServer.on('close', (code) => {
|
96
|
+
if (code !== 0) {
|
97
|
+
console.log(`ls process exited with code ${code}`);
|
98
|
+
}
|
99
|
+
});
|
100
|
+
// Clear timeout once the process exits
|
101
|
+
this.languageServer.on('exit', () => {
|
102
|
+
clearTimeout(this.timeout);
|
103
|
+
console.log('Process terminated cleanly.');
|
104
|
+
});
|
105
|
+
// const logFile = fs.createWriteStream("log.txt");
|
106
|
+
// r.stdout.on('data', (d) => logFile.write(d));
|
107
|
+
}
|
108
|
+
async init() {
|
109
|
+
await this.languageDriver.init(this.lspClient, this.sketchPath);
|
110
|
+
}
|
111
|
+
async run() {
|
112
|
+
// const outputFile = fs.createWriteStream("output.txt");
|
113
|
+
try {
|
114
|
+
await this.init();
|
115
|
+
const holeContext = await this.languageDriver.getHoleContext(this.lspClient, this.sketchPath);
|
116
|
+
const relevantTypes = await this.languageDriver.extractRelevantTypes(this.lspClient, holeContext.fullHoverResult, holeContext.functionName, holeContext.range.start.line, holeContext.range.end.line, new Map(), holeContext.source);
|
117
|
+
// Postprocess the map.
|
118
|
+
if (this.language === types_1.Language.TypeScript) {
|
119
|
+
relevantTypes.delete("_()");
|
120
|
+
for (const [k, { typeSpan: v, sourceFile: src }] of relevantTypes.entries()) {
|
121
|
+
relevantTypes.set(k, { typeSpan: v.slice(0, -1), sourceFile: src });
|
122
|
+
}
|
123
|
+
}
|
124
|
+
else if (this.language === types_1.Language.OCaml) {
|
125
|
+
relevantTypes.delete("_");
|
126
|
+
}
|
127
|
+
console.log(path.join(path.dirname(this.sketchPath), `sketch${path.extname(this.sketchPath)}`));
|
128
|
+
let repo = [];
|
129
|
+
if (this.language === types_1.Language.TypeScript) {
|
130
|
+
repo = (0, utils_1.getAllTSFiles)(this.repoPath);
|
131
|
+
}
|
132
|
+
else if (this.language === types_1.Language.OCaml) {
|
133
|
+
repo = (0, utils_1.getAllOCamlFiles)(this.repoPath);
|
134
|
+
}
|
135
|
+
const relevantHeaders = await this.languageDriver.extractRelevantHeaders(this.lspClient, repo, relevantTypes, holeContext.functionTypeSpan);
|
136
|
+
// Postprocess the map.
|
137
|
+
if (this.language === types_1.Language.TypeScript) {
|
138
|
+
relevantTypes.delete("");
|
139
|
+
for (const [k, { typeSpan: v, sourceFile: src }] of relevantTypes.entries()) {
|
140
|
+
relevantTypes.set(k, { typeSpan: v + ";", sourceFile: src });
|
141
|
+
}
|
142
|
+
for (const obj of relevantHeaders) {
|
143
|
+
obj.typeSpan += ";";
|
144
|
+
}
|
145
|
+
}
|
146
|
+
const relevantTypesToReturn = new Map();
|
147
|
+
relevantTypes.forEach(({ typeSpan: v, sourceFile: src }, _) => {
|
148
|
+
if (relevantTypesToReturn.has(src)) {
|
149
|
+
const updated = relevantTypesToReturn.get(src);
|
150
|
+
updated.push(v);
|
151
|
+
relevantTypesToReturn.set(src, updated);
|
152
|
+
}
|
153
|
+
else {
|
154
|
+
relevantTypesToReturn.set(src, [v]);
|
155
|
+
}
|
156
|
+
});
|
157
|
+
const relevantHeadersToReturn = new Map();
|
158
|
+
relevantHeaders.forEach(({ typeSpan: v, sourceFile: src }) => {
|
159
|
+
if (relevantHeadersToReturn.has(src)) {
|
160
|
+
const updated = relevantHeadersToReturn.get(src);
|
161
|
+
if (!updated.includes(v)) {
|
162
|
+
updated.push(v);
|
163
|
+
}
|
164
|
+
relevantHeadersToReturn.set(src, updated);
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
relevantHeadersToReturn.set(src, [v]);
|
168
|
+
}
|
169
|
+
});
|
170
|
+
this.result = {
|
171
|
+
holeType: holeContext.functionTypeSpan,
|
172
|
+
relevantTypes: relevantTypesToReturn,
|
173
|
+
relevantHeaders: relevantHeadersToReturn
|
174
|
+
};
|
175
|
+
}
|
176
|
+
catch (err) {
|
177
|
+
console.error("Error during execution:", err);
|
178
|
+
throw err;
|
179
|
+
}
|
180
|
+
finally {
|
181
|
+
// outputFile.end();
|
182
|
+
}
|
183
|
+
}
|
184
|
+
close() {
|
185
|
+
// TODO:
|
186
|
+
try {
|
187
|
+
this.lspClient.exit();
|
188
|
+
}
|
189
|
+
catch (err) {
|
190
|
+
console.log(err);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
getSavedResult() {
|
194
|
+
return this.result;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
exports.App = App;
|
198
|
+
class CompletionEngine {
|
199
|
+
constructor(language, sketchPath, configPath) {
|
200
|
+
this.language = language;
|
201
|
+
this.config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
202
|
+
this.sketchPath = sketchPath;
|
203
|
+
}
|
204
|
+
async completeWithLLM(context) {
|
205
|
+
let joinedTypes = "";
|
206
|
+
let joinedHeaders = "";
|
207
|
+
context.relevantTypes.forEach((v, _) => {
|
208
|
+
joinedTypes = joinedTypes + v.join("\n") + "\n";
|
209
|
+
});
|
210
|
+
context.relevantHeaders.forEach((v, _) => {
|
211
|
+
joinedHeaders = joinedHeaders + v.join("\n") + "\n";
|
212
|
+
});
|
213
|
+
// Create a prompt.
|
214
|
+
const prompt = this.generateTypesAndHeadersPrompt(
|
215
|
+
// fs.readFileSync(path.join(targetDirectoryPath, "sketch.ts"), "utf8"),
|
216
|
+
fs.readFileSync(this.sketchPath, "utf8"), context.holeType, joinedTypes, joinedHeaders);
|
217
|
+
// Call the LLM to get completion results back.
|
218
|
+
const apiBase = this.config.apiBase;
|
219
|
+
const deployment = this.config.deployment;
|
220
|
+
const model = this.config.gptModel;
|
221
|
+
const apiVersion = this.config.apiVersion;
|
222
|
+
const apiKey = this.config.apiKey;
|
223
|
+
const openai = new openai_1.default({
|
224
|
+
apiKey,
|
225
|
+
baseURL: `${apiBase}/openai/deployments/${deployment}`,
|
226
|
+
defaultQuery: { "api-version": apiVersion },
|
227
|
+
defaultHeaders: { "api-key": apiKey }
|
228
|
+
});
|
229
|
+
const llmResult = await openai.chat.completions.create({
|
230
|
+
model,
|
231
|
+
messages: prompt,
|
232
|
+
temperature: this.config.temperature
|
233
|
+
});
|
234
|
+
return llmResult.choices[0].message.content;
|
235
|
+
}
|
236
|
+
generateTypesAndHeadersPrompt(sketchFileContent, holeType, relevantTypes, relevantHeaders) {
|
237
|
+
let holeConstruct = "";
|
238
|
+
switch (this.language) {
|
239
|
+
case types_1.Language.TypeScript: {
|
240
|
+
holeConstruct = "_()";
|
241
|
+
}
|
242
|
+
case types_1.Language.OCaml: {
|
243
|
+
holeConstruct = "_";
|
244
|
+
}
|
245
|
+
}
|
246
|
+
const prompt = [{
|
247
|
+
role: "system",
|
248
|
+
content: [
|
249
|
+
"CODE COMPLETION INSTRUCTIONS:",
|
250
|
+
`- Reply with a functional, idiomatic replacement for the program hole marked '${holeConstruct}' in the provided TypeScript program sketch`,
|
251
|
+
`- Reply only with a single replacement term for the unqiue distinguished hole marked '${holeConstruct}'`,
|
252
|
+
"Reply only with code",
|
253
|
+
"- DO NOT include the program sketch in your reply",
|
254
|
+
"- DO NOT include a period at the end of your response and DO NOT use markdown",
|
255
|
+
"- DO NOT include a type signature for the program hole, as this is redundant and is already in the provided program sketch"
|
256
|
+
].join("\n"),
|
257
|
+
}];
|
258
|
+
let userPrompt = {
|
259
|
+
role: "user",
|
260
|
+
content: ""
|
261
|
+
};
|
262
|
+
if (relevantTypes) {
|
263
|
+
userPrompt.content +=
|
264
|
+
`# The expected type of the goal completion is ${holeType} #
|
265
|
+
|
266
|
+
# The following type definitions are likely relevant: #
|
267
|
+
${relevantTypes}
|
268
|
+
|
269
|
+
`;
|
270
|
+
}
|
271
|
+
if (relevantHeaders) {
|
272
|
+
userPrompt.content += `
|
273
|
+
# Consider using these variables relevant to the expected type: #
|
274
|
+
${relevantHeaders}
|
275
|
+
|
276
|
+
`;
|
277
|
+
}
|
278
|
+
userPrompt.content += `# Program Sketch to be completed: #\n${(0, utils_1.removeLines)(sketchFileContent).join("\n")}`;
|
279
|
+
prompt.push(userPrompt);
|
280
|
+
return prompt;
|
281
|
+
}
|
282
|
+
;
|
283
|
+
}
|
284
|
+
exports.CompletionEngine = CompletionEngine;
|
package/dist/codeql.d.ts
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
import { relevantTypeObject, varsObject, typesObject } from "./types";
|
2
|
+
declare const createDatabaseWithCodeQL: (pathToCodeQL: string, targetPath: string) => string;
|
3
|
+
declare const extractHoleType: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => typesObject;
|
4
|
+
declare const extractRelevantTypesWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => Map<string, relevantTypeObject>;
|
5
|
+
declare const extractHeadersWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => Map<string, varsObject>;
|
6
|
+
declare const extractTypesAndLocations: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string) => {
|
7
|
+
locationToType: Map<string, string[]>;
|
8
|
+
typeToLocation: Map<string, string>;
|
9
|
+
};
|
10
|
+
declare const extractRelevantContextWithCodeQL: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, relevantTypes: Map<string, relevantTypeObject>) => Set<string>;
|
11
|
+
declare const getRelevantHeaders: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject) => Set<string>;
|
12
|
+
declare const getRelevantHeaders3: (pathToCodeQL: string, pathToQuery: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject, relevantTypes: Map<string, relevantTypeObject>) => Set<string>;
|
13
|
+
declare const getRelevantHeaders4: (pathToCodeQL: string, pathToQueryDir: string, pathToDatabase: string, outDir: string, headers: Map<string, varsObject>, holeType: typesObject, relevantTypes: Map<string, relevantTypeObject>, knownTypeLocations: {
|
14
|
+
locationToType: Map<string, string[]>;
|
15
|
+
typeToLocation: Map<string, string>;
|
16
|
+
}) => Set<string>;
|
17
|
+
export { createDatabaseWithCodeQL, extractHoleType, extractRelevantTypesWithCodeQL, extractHeadersWithCodeQL, extractRelevantContextWithCodeQL, extractTypesAndLocations, getRelevantHeaders, getRelevantHeaders3, getRelevantHeaders4 };
|