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