@jpoly1219/context-extractor 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/index.js
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.completeWithLLM = exports.extractContext = void 0;
|
4
|
+
var main_1 = require("./main");
|
5
|
+
Object.defineProperty(exports, "extractContext", { enumerable: true, get: function () { return main_1.extractContext; } });
|
6
|
+
var main_2 = require("./main");
|
7
|
+
Object.defineProperty(exports, "completeWithLLM", { enumerable: true, get: function () { return main_2.completeWithLLM; } });
|
package/dist/main.d.ts
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Context, Language } from "./types";
|
2
|
+
export declare const extract: (sketchPath: string) => Promise<{
|
3
|
+
hole: string;
|
4
|
+
relevantTypes: string[];
|
5
|
+
relevantHeaders: string[];
|
6
|
+
}>;
|
7
|
+
export declare const extractWithCodeQL: (sketchPath: string) => Promise<{
|
8
|
+
hole: string;
|
9
|
+
relevantTypes: string[];
|
10
|
+
relevantHeaders: string[];
|
11
|
+
} | undefined>;
|
12
|
+
export declare const extractContext: (language: Language, sketchPath: string, repoPath: string) => Promise<Context | null>;
|
13
|
+
export declare const completeWithLLM: (ctx: Context, language: Language, sketchPath: string, configPath: string) => Promise<string>;
|
package/dist/main.js
ADDED
@@ -0,0 +1,254 @@
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
+
exports.completeWithLLM = exports.extractContext = exports.extractWithCodeQL = exports.extract = void 0;
|
27
|
+
const main_js_1 = require("../ts-lsp-client-dist/src/main.js");
|
28
|
+
const child_process_1 = require("child_process");
|
29
|
+
const fs = __importStar(require("fs"));
|
30
|
+
const path = __importStar(require("path"));
|
31
|
+
const core_1 = require("./core");
|
32
|
+
const codeql_1 = require("./codeql");
|
33
|
+
const constants_1 = require("./constants");
|
34
|
+
const app_1 = require("./app");
|
35
|
+
// sketchPath: /home/<username>/path/to/sketch/dir/sketch.ts
|
36
|
+
const extract = async (sketchPath) => {
|
37
|
+
const logFile = fs.createWriteStream("log.txt");
|
38
|
+
const rootPath = path.dirname(sketchPath);
|
39
|
+
const rootUri = `file://${rootPath}`;
|
40
|
+
const sketchFileName = path.basename(sketchPath);
|
41
|
+
const workspaceFolders = [{ 'name': 'context-extractor', 'uri': rootUri }];
|
42
|
+
// initialize LS client and server
|
43
|
+
const r = (0, child_process_1.spawn)('typescript-language-server', ['--stdio']);
|
44
|
+
const e = new main_js_1.JSONRPCEndpoint(r.stdin, r.stdout);
|
45
|
+
const c = new main_js_1.LspClient(e);
|
46
|
+
console.log(JSON.stringify(c));
|
47
|
+
const capabilities = {
|
48
|
+
'textDocument': {
|
49
|
+
'codeAction': { 'dynamicRegistration': true },
|
50
|
+
'codeLens': { 'dynamicRegistration': true },
|
51
|
+
'colorProvider': { 'dynamicRegistration': true },
|
52
|
+
'completion': {
|
53
|
+
'completionItem': {
|
54
|
+
'commitCharactersSupport': true,
|
55
|
+
'documentationFormat': ['markdown', 'plaintext'],
|
56
|
+
'snippetSupport': true
|
57
|
+
},
|
58
|
+
'completionItemKind': {
|
59
|
+
'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
|
60
|
+
},
|
61
|
+
'contextSupport': true,
|
62
|
+
'dynamicRegistration': true
|
63
|
+
},
|
64
|
+
'definition': { 'dynamicRegistration': true },
|
65
|
+
'documentHighlight': { 'dynamicRegistration': true },
|
66
|
+
'documentLink': { 'dynamicRegistration': true },
|
67
|
+
'documentSymbol': {
|
68
|
+
'dynamicRegistration': true,
|
69
|
+
'symbolKind': {
|
70
|
+
'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
|
71
|
+
}
|
72
|
+
},
|
73
|
+
'formatting': { 'dynamicRegistration': true },
|
74
|
+
'hover': {
|
75
|
+
'contentFormat': ['markdown', 'plaintext'],
|
76
|
+
'dynamicRegistration': true
|
77
|
+
},
|
78
|
+
'implementation': { 'dynamicRegistration': true },
|
79
|
+
// 'inlayhint': { 'dynamicRegistration': true },
|
80
|
+
'onTypeFormatting': { 'dynamicRegistration': true },
|
81
|
+
'publishDiagnostics': { 'relatedInformation': true },
|
82
|
+
'rangeFormatting': { 'dynamicRegistration': true },
|
83
|
+
'references': { 'dynamicRegistration': true },
|
84
|
+
'rename': { 'dynamicRegistration': true },
|
85
|
+
'signatureHelp': {
|
86
|
+
'dynamicRegistration': true,
|
87
|
+
'signatureInformation': { 'documentationFormat': ['markdown', 'plaintext'] }
|
88
|
+
},
|
89
|
+
'synchronization': {
|
90
|
+
'didSave': true,
|
91
|
+
'dynamicRegistration': true,
|
92
|
+
'willSave': true,
|
93
|
+
'willSaveWaitUntil': true
|
94
|
+
},
|
95
|
+
'typeDefinition': { 'dynamicRegistration': true, 'linkSupport': true },
|
96
|
+
// 'typeHierarchy': { 'dynamicRegistration': true }
|
97
|
+
},
|
98
|
+
'workspace': {
|
99
|
+
'applyEdit': true,
|
100
|
+
'configuration': true,
|
101
|
+
'didChangeConfiguration': { 'dynamicRegistration': true },
|
102
|
+
'didChangeWatchedFiles': { 'dynamicRegistration': true },
|
103
|
+
'executeCommand': { 'dynamicRegistration': true },
|
104
|
+
'symbol': {
|
105
|
+
'dynamicRegistration': true,
|
106
|
+
'symbolKind': {
|
107
|
+
'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
|
108
|
+
}
|
109
|
+
}, 'workspaceEdit': { 'documentChanges': true },
|
110
|
+
'workspaceFolders': true
|
111
|
+
},
|
112
|
+
'general': {
|
113
|
+
'positionEncodings': ['utf-8']
|
114
|
+
},
|
115
|
+
};
|
116
|
+
r.stdout.on('data', (d) => logFile.write(d));
|
117
|
+
await c.initialize({
|
118
|
+
processId: process.pid,
|
119
|
+
capabilities: capabilities,
|
120
|
+
trace: 'off',
|
121
|
+
rootUri: null,
|
122
|
+
workspaceFolders: workspaceFolders,
|
123
|
+
initializationOptions: {
|
124
|
+
preferences: {
|
125
|
+
includeInlayVariableTypeHints: true
|
126
|
+
}
|
127
|
+
}
|
128
|
+
});
|
129
|
+
// inject hole function
|
130
|
+
const injectedSketchPath = `${rootPath}/injected_${sketchFileName}`;
|
131
|
+
const injectedSketchUri = `file://${injectedSketchPath}`;
|
132
|
+
const sketchFileContent = fs.readFileSync(sketchPath, "utf8");
|
133
|
+
const injectedSketchFileContent = `declare function _<T>(): T\n${sketchFileContent}`;
|
134
|
+
fs.writeFileSync(injectedSketchPath, injectedSketchFileContent);
|
135
|
+
// doucment sync client and server by notifying that the client has opened all the files inside the target directory
|
136
|
+
fs.readdirSync(rootPath).map(fileName => {
|
137
|
+
if (fs.lstatSync(`${rootPath}/${fileName}`).isFile()) {
|
138
|
+
c.didOpen({
|
139
|
+
textDocument: {
|
140
|
+
uri: `file://${rootPath}/${fileName}`,
|
141
|
+
languageId: 'typescript',
|
142
|
+
text: fs.readFileSync(`${rootPath}/${fileName}`).toString("ascii"),
|
143
|
+
version: 1
|
144
|
+
}
|
145
|
+
});
|
146
|
+
}
|
147
|
+
});
|
148
|
+
// get context of the hole
|
149
|
+
// currently only matching ES6 arrow functions
|
150
|
+
const holeContext = await (0, core_1.getHoleContext)(c, injectedSketchUri, injectedSketchFileContent);
|
151
|
+
// console.log(holeContext);
|
152
|
+
// rewrite hole function after context has been extracted to make LSP work
|
153
|
+
const trueHoleFunction = `declare function _(): ${holeContext.functionTypeSpan}`;
|
154
|
+
const trueInjectedSketchFileContent = `${trueHoleFunction}\n${sketchFileContent}`;
|
155
|
+
fs.writeFileSync(injectedSketchPath, trueInjectedSketchFileContent);
|
156
|
+
c.didChange({
|
157
|
+
textDocument: {
|
158
|
+
uri: injectedSketchUri,
|
159
|
+
version: 2
|
160
|
+
},
|
161
|
+
contentChanges: [{
|
162
|
+
text: trueInjectedSketchFileContent
|
163
|
+
}]
|
164
|
+
});
|
165
|
+
// recursively define relevant types
|
166
|
+
const outputFile = fs.createWriteStream("output.txt");
|
167
|
+
// const foundSoFar = new Map<string, string>();
|
168
|
+
const relevantTypes = await (0, core_1.extractRelevantTypes)(c, holeContext.fullHoverResult, holeContext.functionName, holeContext.functionTypeSpan, 0, "declare function _(): ".length, new Map(), injectedSketchUri, outputFile, 1);
|
169
|
+
relevantTypes.delete("_");
|
170
|
+
relevantTypes.delete("_()");
|
171
|
+
for (const [k, v] of relevantTypes.entries()) {
|
172
|
+
relevantTypes.set(k, v.slice(0, -1));
|
173
|
+
}
|
174
|
+
// console.log("relevantTypes:", relevantTypes);
|
175
|
+
logFile.end();
|
176
|
+
logFile.close();
|
177
|
+
outputFile.end();
|
178
|
+
outputFile.close();
|
179
|
+
const preludeContent = fs.readFileSync(`${rootPath}/prelude.ts`).toString("utf8");
|
180
|
+
const relevantHeaders = (0, core_1.extractRelevantHeaders)(preludeContent, relevantTypes, holeContext.functionTypeSpan);
|
181
|
+
for (const [k, v] of relevantTypes.entries()) {
|
182
|
+
relevantTypes.set(k, v + ";");
|
183
|
+
}
|
184
|
+
for (let i = 0; i < relevantHeaders.length; ++i) {
|
185
|
+
relevantHeaders[i] += ";";
|
186
|
+
}
|
187
|
+
// console.log(relevantContext);
|
188
|
+
// return { holeContext: holeContext, relevantTypes: Array.from(relevantTypes), relevantContext: relevantContext };
|
189
|
+
return { hole: holeContext.functionTypeSpan, relevantTypes: Array.from(relevantTypes, ([k, v]) => { return v; }), relevantHeaders: relevantHeaders };
|
190
|
+
};
|
191
|
+
exports.extract = extract;
|
192
|
+
const extractWithCodeQL = async (sketchPath) => {
|
193
|
+
const start = Date.now();
|
194
|
+
console.log("ROOT_DIR: ", constants_1.ROOT_DIR);
|
195
|
+
console.log("DEPS_DIR: ", constants_1.DEPS_DIR);
|
196
|
+
console.log("CODEQL_PATH: ", constants_1.CODEQL_PATH);
|
197
|
+
const targetPath = path.dirname(sketchPath);
|
198
|
+
try {
|
199
|
+
// extraction
|
200
|
+
const databasePath = (0, codeql_1.createDatabaseWithCodeQL)(constants_1.CODEQL_PATH, targetPath);
|
201
|
+
const holeType = (0, codeql_1.extractHoleType)(constants_1.CODEQL_PATH, path.join(constants_1.QUERY_DIR, "hole.ql"), databasePath, targetPath);
|
202
|
+
// console.log("holeType: ", holeType);
|
203
|
+
const relevantTypes = (0, codeql_1.extractRelevantTypesWithCodeQL)(constants_1.CODEQL_PATH, path.join(constants_1.QUERY_DIR, "relevant-types.ql"), databasePath, targetPath);
|
204
|
+
// console.log("relevantTypes: ", Array.from(relevantTypes, ([k, v]) => { return v.typeAliasDeclaration; }));
|
205
|
+
// console.log("relevantTypes: ", relevantTypes)
|
206
|
+
const headers = (0, codeql_1.extractHeadersWithCodeQL)(constants_1.CODEQL_PATH, path.join(constants_1.QUERY_DIR, "vars.ql"), databasePath, targetPath);
|
207
|
+
// console.log("headers: ", headers)
|
208
|
+
// const relevantContext = extractRelevantContextWithCodeQL(CODEQL_PATH, path.join(QUERY_DIR, "types.ql"), databasePath, targetPath, headers, relevantTypes);
|
209
|
+
// console.log("relevantContext: ", relevantContext);
|
210
|
+
// const relevantHeaders = getRelevantHeaders(CODEQL_PATH, path.join(QUERY_DIR, "types.ql"), databasePath, targetPath, headers, holeType);
|
211
|
+
// console.log("relevantHeaders: ", relevantHeaders);
|
212
|
+
const knownTypeLocations = (0, codeql_1.extractTypesAndLocations)(constants_1.CODEQL_PATH, path.join(constants_1.QUERY_DIR, "imports.ql"), databasePath, targetPath);
|
213
|
+
// console.log("known type locations: ", knownTypeLocations)
|
214
|
+
// NOTE: switch between the two header extraction methods
|
215
|
+
// const relevantHeaders = getRelevantHeaders3(CODEQL_PATH, path.join(QUERY_DIR, "types.ql"), databasePath, targetPath, headers, holeType, relevantTypes);
|
216
|
+
// console.log("relevantHeaders: ", Array.from(relevantHeaders));
|
217
|
+
const relevantHeaders = (0, codeql_1.getRelevantHeaders4)(constants_1.CODEQL_PATH, constants_1.QUERY_DIR, databasePath, targetPath, headers, holeType, relevantTypes, knownTypeLocations);
|
218
|
+
// console.log("relevantHeaders: ", Array.from(relevantHeaders));
|
219
|
+
const end = Date.now();
|
220
|
+
// console.log("end: ", end)
|
221
|
+
// console.log("elapsed: ", end - start)
|
222
|
+
return { hole: holeType.typeName, relevantTypes: Array.from(relevantTypes, ([k, v]) => { return JSON.stringify(v); }), relevantHeaders: Array.from(relevantHeaders) };
|
223
|
+
}
|
224
|
+
catch (err) {
|
225
|
+
console.error(`${targetPath}: ${err}`);
|
226
|
+
}
|
227
|
+
};
|
228
|
+
exports.extractWithCodeQL = extractWithCodeQL;
|
229
|
+
const extractContext = async (language, sketchPath, repoPath) => {
|
230
|
+
const app = new app_1.App(language, sketchPath, repoPath);
|
231
|
+
await app.run();
|
232
|
+
const res = app.getSavedResult();
|
233
|
+
app.close();
|
234
|
+
return res;
|
235
|
+
// if (!getCompletion) {
|
236
|
+
// await app.close()
|
237
|
+
// return { context: res, completion: "" };
|
238
|
+
// } else {
|
239
|
+
// if (res) {
|
240
|
+
// const completion = await app.completeWithLLM(path.dirname(sketchPath), res);
|
241
|
+
// await app.close()
|
242
|
+
// return { context: res, completion: completion };
|
243
|
+
// }
|
244
|
+
// await app.close()
|
245
|
+
// return { context: null, completion: null };
|
246
|
+
// }
|
247
|
+
};
|
248
|
+
exports.extractContext = extractContext;
|
249
|
+
const completeWithLLM = async (ctx, language, sketchPath, configPath) => {
|
250
|
+
const engine = new app_1.CompletionEngine(language, sketchPath, configPath);
|
251
|
+
const completion = await engine.completeWithLLM(ctx);
|
252
|
+
return completion;
|
253
|
+
};
|
254
|
+
exports.completeWithLLM = completeWithLLM;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { LspClient, Range } from "../ts-lsp-client-dist/src/main";
|
2
|
+
import { LanguageDriver, TypeSpanAndSourceFile } from "./types";
|
3
|
+
import { OcamlTypeChecker } from "./ocaml-type-checker";
|
4
|
+
export declare class OcamlDriver implements LanguageDriver {
|
5
|
+
typeChecker: OcamlTypeChecker;
|
6
|
+
init(lspClient: LspClient, sketchPath: string): Promise<void>;
|
7
|
+
getHoleContext(lspClient: LspClient, sketchFilePath: string): Promise<{
|
8
|
+
fullHoverResult: string;
|
9
|
+
functionName: string;
|
10
|
+
functionTypeSpan: any;
|
11
|
+
linePosition: any;
|
12
|
+
characterPosition: any;
|
13
|
+
holeTypeDefLinePos: number;
|
14
|
+
holeTypeDefCharPos: number;
|
15
|
+
range: Range;
|
16
|
+
source: string;
|
17
|
+
}>;
|
18
|
+
extractRelevantTypes(lspClient: LspClient, fullHoverResult: string, typeName: string, startLine: number, endLine: number, foundSoFar: Map<string, TypeSpanAndSourceFile>, currentFile: string): Promise<Map<string, TypeSpanAndSourceFile>>;
|
19
|
+
extractRelevantHeaders(lspClient: LspClient, sources: string[], relevantTypes: Map<string, TypeSpanAndSourceFile>, holeType: string): Promise<Set<TypeSpanAndSourceFile>>;
|
20
|
+
extractHeaderTypeSpans(lspClient: LspClient, preludeFilePath: string): Promise<{
|
21
|
+
identifier: string;
|
22
|
+
typeSpan: string;
|
23
|
+
snippet: string;
|
24
|
+
}[]>;
|
25
|
+
generateTargetTypes(holeType: string, relevantTypes: Map<string, TypeSpanAndSourceFile>, preludeFilePath: string): Set<string>;
|
26
|
+
generateTargetTypesHelper(relevantTypes: Map<string, TypeSpanAndSourceFile>, currType: string, targetTypes: Set<string>): void;
|
27
|
+
extractRelevantHeadersHelper(typeSpan: string, targetTypes: Set<string>, relevantTypes: Map<string, TypeSpanAndSourceFile>, relevantContext: Set<TypeSpanAndSourceFile>, snippet: string, source: string): void;
|
28
|
+
isTypeEquivalent(t1: string, t2: string, relevantTypes: Map<string, TypeSpanAndSourceFile>): boolean;
|
29
|
+
normalize(typeSpan: string, relevantTypes: Map<string, TypeSpanAndSourceFile>): string | undefined;
|
30
|
+
}
|