@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/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
|
+
}
|