@jpoly1219/context-extractor 0.1.2 → 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/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
+ }