@jpoly1219/context-extractor 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ declare const ROOT_DIR: string;
2
+ declare const DEPS_DIR: string;
3
+ declare const CODEQL_PATH: string;
4
+ declare const QUERY_DIR: string;
5
+ declare const TARGET_DIR: string;
6
+ declare const TODO_DIR: string;
7
+ declare const PLAYLIST_DIR: string;
8
+ declare const PASSWORDS_DIR: string;
9
+ declare const BOOKING_DIR: string;
10
+ declare const EMOJIPAINT_DIR: string;
11
+ export { CODEQL_PATH, ROOT_DIR, DEPS_DIR, QUERY_DIR, TARGET_DIR, TODO_DIR, PLAYLIST_DIR, PASSWORDS_DIR, BOOKING_DIR, EMOJIPAINT_DIR };
@@ -0,0 +1,62 @@
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.EMOJIPAINT_DIR = exports.BOOKING_DIR = exports.PASSWORDS_DIR = exports.PLAYLIST_DIR = exports.TODO_DIR = exports.TARGET_DIR = exports.QUERY_DIR = exports.DEPS_DIR = exports.ROOT_DIR = exports.CODEQL_PATH = void 0;
27
+ // import * as path from "path";
28
+ // import * as process from "process";
29
+ //
30
+ //
31
+ // const ROOT_DIR = process.cwd();
32
+ // const CODEQL_PATH = path.join(ROOT_DIR, "codeql", "codeql");
33
+ // const QUERY_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "queries", "codeql-custom-queries-javascript");
34
+ // const TARGET_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets");
35
+ // const TODO_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets", "todo");
36
+ // const PLAYLIST_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets", "playlist");
37
+ // const PASSWORDS_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets", "passwords");
38
+ // const BOOKING_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets", "booking");
39
+ // const EMOJIPAINT_DIR = path.join("/", "home", "jacob", "projects", "context-extractor", "targets", "emojipaint");
40
+ //
41
+ // export { CODEQL_PATH, ROOT_DIR, QUERY_DIR, TARGET_DIR, TODO_DIR, PLAYLIST_DIR, PASSWORDS_DIR, BOOKING_DIR, EMOJIPAINT_DIR };
42
+ const path = __importStar(require("path"));
43
+ const ROOT_DIR = path.join("/", "app");
44
+ exports.ROOT_DIR = ROOT_DIR;
45
+ const DEPS_DIR = path.join(ROOT_DIR, "deps");
46
+ exports.DEPS_DIR = DEPS_DIR;
47
+ const CODEQL_PATH = path.join(DEPS_DIR, "codeql", "codeql");
48
+ exports.CODEQL_PATH = CODEQL_PATH;
49
+ const QUERY_DIR = path.join(DEPS_DIR, "queries", "codeql-custom-queries-javascript");
50
+ exports.QUERY_DIR = QUERY_DIR;
51
+ const TARGET_DIR = path.join(DEPS_DIR, "targets");
52
+ exports.TARGET_DIR = TARGET_DIR;
53
+ const TODO_DIR = path.join(DEPS_DIR, "targets", "todo");
54
+ exports.TODO_DIR = TODO_DIR;
55
+ const PLAYLIST_DIR = path.join(DEPS_DIR, "targets", "playlist");
56
+ exports.PLAYLIST_DIR = PLAYLIST_DIR;
57
+ const PASSWORDS_DIR = path.join(DEPS_DIR, "targets", "passwords");
58
+ exports.PASSWORDS_DIR = PASSWORDS_DIR;
59
+ const BOOKING_DIR = path.join(DEPS_DIR, "targets", "booking");
60
+ exports.BOOKING_DIR = BOOKING_DIR;
61
+ const EMOJIPAINT_DIR = path.join(DEPS_DIR, "targets", "emojipaint");
62
+ exports.EMOJIPAINT_DIR = EMOJIPAINT_DIR;
package/dist/core.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /// <reference types="node" />
2
+ import { LspClient } from "../ts-lsp-client-dist/src/main.js";
3
+ import * as fs from "fs";
4
+ declare const getAnnotatedFunctionHoleContext: (sketchFileContent: string) => {
5
+ functionName: string;
6
+ functionTypeSpan: string;
7
+ linePosition: number;
8
+ characterPosition: number;
9
+ };
10
+ declare const getHoleContext: (c: LspClient, injectedSketchFilePath: string, injectedSketchFileContent: string) => Promise<{
11
+ fullHoverResult: string;
12
+ functionName: string;
13
+ functionTypeSpan: string;
14
+ linePosition: number;
15
+ characterPosition: number;
16
+ }>;
17
+ declare const extractRelevantTypes: (c: LspClient, fullHoverResult: string, typeName: string, typeSpan: string, linePosition: number, characterPosition: number, foundSoFar: Map<string, string>, currentFile: string, outputFile: fs.WriteStream, depth: number) => Promise<Map<string, string>>;
18
+ declare const extractRelevantHeaders: (preludeContent: string, relevantTypes: Map<string, string>, holeType: string) => string[];
19
+ declare const normalize: (typeSpan: string, relevantTypes: Map<string, string>) => string;
20
+ export { getAnnotatedFunctionHoleContext, getHoleContext, extractRelevantTypes, extractRelevantHeaders, normalize };
package/dist/core.js ADDED
@@ -0,0 +1,576 @@
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.normalize = exports.extractRelevantHeaders = exports.extractRelevantTypes = exports.getHoleContext = exports.getAnnotatedFunctionHoleContext = void 0;
27
+ const utils_js_1 = require("./utils.js");
28
+ const fs = __importStar(require("fs"));
29
+ const child_process_1 = require("child_process");
30
+ // get context of the hole
31
+ // currently only matching ES6 arrow functions
32
+ const getAnnotatedFunctionHoleContext = (sketchFileContent) => {
33
+ const es6AnnotatedArrowFunctionPattern = /(const )(.+)(: )(\(.+\) => .+)( =[\s\S]*_())/;
34
+ const firstPatternIndex = sketchFileContent.search(es6AnnotatedArrowFunctionPattern);
35
+ const match = sketchFileContent.match(es6AnnotatedArrowFunctionPattern);
36
+ const functionName = match[2];
37
+ const functionTypeSpan = match[4];
38
+ const linePosition = (sketchFileContent.substring(0, firstPatternIndex).match(/\n/g)).length;
39
+ const characterPosition = (0, utils_js_1.indexOfRegexGroup)(match, 4) - firstPatternIndex;
40
+ return { functionName: functionName, functionTypeSpan: functionTypeSpan, linePosition: linePosition, characterPosition: characterPosition };
41
+ };
42
+ exports.getAnnotatedFunctionHoleContext = getAnnotatedFunctionHoleContext;
43
+ // get context of the hole using hole function
44
+ const getHoleContext = async (c, injectedSketchFilePath, injectedSketchFileContent) => {
45
+ const holePattern = /_\(\)/;
46
+ const firstPatternIndex = injectedSketchFileContent.search(holePattern);
47
+ const linePosition = (injectedSketchFileContent.substring(0, firstPatternIndex).match(/\n/g)).length;
48
+ const characterPosition = firstPatternIndex - injectedSketchFileContent.split("\n", linePosition).join("\n").length - 1;
49
+ const holeHoverResult = await c.hover({
50
+ textDocument: {
51
+ uri: injectedSketchFilePath
52
+ },
53
+ position: {
54
+ character: characterPosition,
55
+ line: linePosition
56
+ }
57
+ });
58
+ const formattedHoverResult = holeHoverResult.contents.value.split("\n").reduce((acc, curr) => {
59
+ if (curr != "" && curr != "```typescript" && curr != "```") {
60
+ return acc + curr;
61
+ }
62
+ else {
63
+ return acc;
64
+ }
65
+ }, "");
66
+ // function _<(a: Apple, c: Cherry, b: Banana) => Cherry > (): (a: Apple, c: Cherry, b: Banana) => Cherry
67
+ const holeFunctionPattern = /(function _)(\<.+\>)(\(\): )(.+)/;
68
+ const match = formattedHoverResult.match(holeFunctionPattern);
69
+ const functionName = "_()";
70
+ const functionTypeSpan = match[4];
71
+ return { fullHoverResult: formattedHoverResult, functionName: functionName, functionTypeSpan: functionTypeSpan, linePosition: linePosition, characterPosition: characterPosition };
72
+ };
73
+ exports.getHoleContext = getHoleContext;
74
+ // // get target types given a type span
75
+ // const getTargetTypes = (typeSpan: string, aliasContext: string) => {
76
+ // // (Model, Action) => Model
77
+ // // if the expected type is an arrow type, the return type is a target type.
78
+ // // if the return type is a product type, its elements are target types.
79
+ //
80
+ // const targetTypes = [];
81
+ // targetTypes.push(typeSpan);
82
+ // const arrowPattern = /(\(.+\))( => )(.+)/;
83
+ // const arrowMatch = typeSpan.match(arrowPattern);
84
+ // if (arrowMatch) {
85
+ // const returnType = arrowMatch[3];
86
+ // targetTypes.push(returnType);
87
+ //
88
+ // const tuplePattern = /(\[.+\])/;
89
+ // if (aliasContext.has(returnType)) {
90
+ // const alias = aliasContext.get(returnType);
91
+ // console.log(alias)
92
+ // const tupleMatch = alias.match(tuplePattern);
93
+ //
94
+ // if (tupleMatch) {
95
+ // alias.slice(1, alias.length - 1).split(",").map((typ) => targetTypes.push(typ));
96
+ // }
97
+ // }
98
+ // }
99
+ // console.log("targetTypes: ", targetTypes);
100
+ // return targetTypes;
101
+ // }
102
+ // pattern matching
103
+ // attempts to match strings to corresponding types, then returns an object containing the name, type span, and an interesting index
104
+ // base case - type can no longer be stepped into
105
+ // boolean, number, string, enum, unknown, any, void, null, undefined, never
106
+ // ideally this should be checked for before we do the for loop
107
+ // return typeSpan;
108
+ // check if hover result is from a primitive type
109
+ const checkPrimitive = (typeDefinition) => {
110
+ // type _ = boolean
111
+ const primitivePattern = /(type )(.+)( = )(.+)/;
112
+ const primitiveMatch = typeDefinition.match(primitivePattern);
113
+ let primitiveInterestingIndex = -1;
114
+ if (primitiveMatch) {
115
+ primitiveInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(primitiveMatch, 4);
116
+ }
117
+ if (primitiveInterestingIndex != -1) {
118
+ const typeName = primitiveMatch[2];
119
+ const typeSpan = primitiveMatch[4];
120
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: primitiveInterestingIndex };
121
+ }
122
+ return null;
123
+ };
124
+ // check if hover result is from an import
125
+ const checkImports = (typeDefinition) => {
126
+ // import { _, _ };
127
+ const importPattern = /(import )(\{.+\})/;
128
+ const importMatch = typeDefinition.match(importPattern);
129
+ let importInterestingIndex = -1;
130
+ if (importMatch) {
131
+ importInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(importMatch, 2);
132
+ }
133
+ // import _;
134
+ const defaultImportPattern = /(import )(.+)/;
135
+ const defaultImportMatch = typeDefinition.match(defaultImportPattern);
136
+ let defaultImportInterestingIndex = -1;
137
+ if (defaultImportMatch) {
138
+ defaultImportInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(defaultImportMatch, 2);
139
+ }
140
+ if (importInterestingIndex != -1) {
141
+ const typeName = importMatch[2];
142
+ const typeSpan = importMatch[2];
143
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: importInterestingIndex };
144
+ }
145
+ else if (defaultImportInterestingIndex != -1) {
146
+ const typeName = defaultImportMatch[2];
147
+ const typeSpan = defaultImportMatch[2];
148
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: defaultImportInterestingIndex };
149
+ }
150
+ return null;
151
+ };
152
+ // check if hover result is from a module
153
+ const checkModule = (typeDefinition) => {
154
+ // module "path/to/module"
155
+ const modulePattern = /(module )(.+)/;
156
+ const moduleMatch = typeDefinition.match(modulePattern);
157
+ let moduleInterestingIndex = -1;
158
+ if (moduleMatch) {
159
+ moduleInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(moduleMatch, 2);
160
+ }
161
+ if (moduleInterestingIndex != -1) {
162
+ const typeName = moduleMatch[2];
163
+ const typeSpan = moduleMatch[2];
164
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: moduleInterestingIndex };
165
+ }
166
+ return null;
167
+ };
168
+ // check if hover result is from an object
169
+ const checkObject = (typeDefinition) => {
170
+ // type _ = {
171
+ // _: t1;
172
+ // _: t2;
173
+ // }
174
+ const objectTypeDefPattern = /(type )(.+)( = )(\{.+\})/;
175
+ const objectTypeDefMatch = typeDefinition.match(objectTypeDefPattern);
176
+ let objectTypeDefInterestingIndex = -1;
177
+ if (objectTypeDefMatch) {
178
+ objectTypeDefInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(objectTypeDefMatch, 4);
179
+ }
180
+ if (objectTypeDefInterestingIndex != -1) {
181
+ const typeName = objectTypeDefMatch[2];
182
+ const typeSpan = objectTypeDefMatch[4];
183
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: objectTypeDefInterestingIndex };
184
+ }
185
+ return null;
186
+ };
187
+ // check if hover result is from a union
188
+ const checkUnion = (typeDefinition) => {
189
+ // type _ = A | B | C
190
+ const unionPattern = /(type )(.+)( = )((.+ | )+.+)/;
191
+ const unionMatch = typeDefinition.match(unionPattern);
192
+ let unionInterestingIndex = -1;
193
+ if (unionMatch) {
194
+ unionInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(unionMatch, 4);
195
+ }
196
+ if (unionInterestingIndex != -1) {
197
+ const typeName = unionMatch[2];
198
+ const typeSpan = unionMatch[4];
199
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: unionInterestingIndex };
200
+ }
201
+ return null;
202
+ };
203
+ // check if hover result is from a function
204
+ const checkFunction = (typeDefinition) => {
205
+ // const myFunc : (arg1: typ1, ...) => _
206
+ const es6AnnotatedFunctionPattern = /(const )(.+)(: )(\(.+\) => .+)/;
207
+ const es6AnnotatedFunctionMatch = typeDefinition.match(es6AnnotatedFunctionPattern);
208
+ let es6AnnotatedFunctionInterestingIndex = -1;
209
+ if (es6AnnotatedFunctionMatch) {
210
+ es6AnnotatedFunctionInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(es6AnnotatedFunctionMatch, 4);
211
+ }
212
+ // type _ = (_: t1) => t2
213
+ const es6FunctionTypeDefPattern = /(type )(.+)( = )(\(.+\) => .+)/;
214
+ const es6FunctionTypeDefPatternMatch = typeDefinition.match(es6FunctionTypeDefPattern);
215
+ let es6FunctionTypeDefInterestingIndex = -1;
216
+ if (es6FunctionTypeDefPatternMatch) {
217
+ es6FunctionTypeDefInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(es6FunctionTypeDefPatternMatch, 4);
218
+ }
219
+ // function myFunc<T>(args: types, genarg: T): returntype
220
+ const genericFunctionTypePattern = /(function )(.+)(\<.+\>\(.*\))(: )(.+)/;
221
+ const genericFunctionTypeMatch = typeDefinition.match(genericFunctionTypePattern);
222
+ let genericFunctionTypeInterestingIndex = -1;
223
+ if (genericFunctionTypeMatch) {
224
+ genericFunctionTypeInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(genericFunctionTypeMatch, 3);
225
+ }
226
+ // function myFunc(args: types): returntype
227
+ const functionTypePattern = /(function )(.+)(\(.*\))(: )(.+)/;
228
+ const functionTypeMatch = typeDefinition.match(functionTypePattern);
229
+ let functionTypeInterestingIndex = -1;
230
+ if (functionTypeMatch) {
231
+ functionTypeInterestingIndex = (0, utils_js_1.indexOfRegexGroup)(functionTypeMatch, 3);
232
+ }
233
+ if (es6AnnotatedFunctionInterestingIndex != -1) {
234
+ const typeName = es6AnnotatedFunctionMatch[2];
235
+ const typeSpan = es6AnnotatedFunctionMatch[4];
236
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: es6AnnotatedFunctionInterestingIndex };
237
+ }
238
+ else if (es6FunctionTypeDefInterestingIndex != -1) {
239
+ const typeName = es6FunctionTypeDefPatternMatch[2];
240
+ const typeSpan = es6FunctionTypeDefPatternMatch[4];
241
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: es6FunctionTypeDefInterestingIndex };
242
+ }
243
+ else if (genericFunctionTypeInterestingIndex != -1) {
244
+ const typeName = genericFunctionTypeMatch[2];
245
+ const typeSpan = genericFunctionTypeMatch[3] + genericFunctionTypeMatch[4] + genericFunctionTypeMatch[5];
246
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: genericFunctionTypeInterestingIndex };
247
+ }
248
+ else if (functionTypeInterestingIndex != -1) {
249
+ const typeName = functionTypeMatch[2];
250
+ const typeSpan = functionTypeMatch[3] + functionTypeMatch[4] + functionTypeMatch[5];
251
+ return { typeName: typeName, typeSpan: typeSpan, interestingIndex: functionTypeInterestingIndex };
252
+ }
253
+ return null;
254
+ };
255
+ // check if hover result is from a hole
256
+ const checkHole = (typeDefinition) => {
257
+ // (type parameter) T in _<T>(): T
258
+ const holePattern = /(\(type parameter\) T in _\<T\>\(\): T)/;
259
+ const match = typeDefinition.match(holePattern);
260
+ if (match) {
261
+ const typeName = "hole function";
262
+ const typeSpan = match[1];
263
+ return { typeName: typeName, typeSpan: typeSpan };
264
+ }
265
+ return null;
266
+ };
267
+ // check if hover result is from a parameter
268
+ const checkParameter = (typeDefinition) => {
269
+ // (parameter) name: type
270
+ // const parameterPattern = /(\(parameter\) )(.+)(: )(.+))/;
271
+ // const parameterMatch = typeDefinition.match(parameterPattern);
272
+ // let parameterInterestingIndex = -1;
273
+ // if (parameterMatch) {
274
+ // parameterInterestingIndex = indexOfRegexGroup(parameterMatch, 4);
275
+ // }
276
+ //
277
+ // if (parameterInterestingIndex != -1) {
278
+ // const typeName = parameterMatch[2];
279
+ // const typeSpan = parameterMatch[4];
280
+ // return { typeName: typeName, typeSpan: typeSpan, interestingIndex: parameterInterestingIndex }
281
+ // }
282
+ return null;
283
+ };
284
+ // get type context from hover result
285
+ const getTypeContext = (typeDefinition) => {
286
+ if (checkHole(typeDefinition)) {
287
+ return checkHole(typeDefinition);
288
+ }
289
+ else if (checkParameter(typeDefinition)) {
290
+ return checkParameter(typeDefinition);
291
+ }
292
+ else if (checkFunction(typeDefinition)) {
293
+ return checkFunction(typeDefinition);
294
+ }
295
+ else if (checkUnion(typeDefinition)) {
296
+ return checkUnion(typeDefinition);
297
+ }
298
+ else if (checkObject(typeDefinition)) {
299
+ return checkObject(typeDefinition);
300
+ }
301
+ else if (checkImports(typeDefinition)) {
302
+ return checkImports(typeDefinition);
303
+ }
304
+ else if (checkModule(typeDefinition)) {
305
+ return checkModule(typeDefinition);
306
+ }
307
+ else {
308
+ return checkPrimitive(typeDefinition);
309
+ }
310
+ };
311
+ // recursively extract type definitions
312
+ // given the span of a type annotation on a function, return a list of names and positions for all type aliases used in that annotation
313
+ // find the span of a type definition: specialize to the case where it is a single struct
314
+ // recurse through array, tuple, object
315
+ const extractRelevantTypes = async (c, fullHoverResult, typeName, typeSpan, linePosition, characterPosition, foundSoFar, currentFile, outputFile, depth) => {
316
+ if (!foundSoFar.has(typeName)) {
317
+ foundSoFar.set(typeName, fullHoverResult);
318
+ outputFile.write(`${fullHoverResult};\n`);
319
+ // approach 1: go to type definition and hover
320
+ const content = fs.readFileSync(currentFile.slice(7), "utf8");
321
+ const charInLine = (0, child_process_1.execSync)(`wc -m <<< "${content.split("\n")[linePosition].slice(characterPosition)}"`, { shell: "/bin/bash" });
322
+ // -1 is done to avoid tsserver errors
323
+ for (let i = 0; i < Math.min(parseInt(charInLine.toString()), typeSpan.length) - 1; i++) {
324
+ try {
325
+ const typeDefinitionResult = await c.typeDefinition({
326
+ textDocument: {
327
+ uri: currentFile
328
+ },
329
+ position: {
330
+ character: characterPosition + i,
331
+ line: linePosition
332
+ }
333
+ });
334
+ if (typeDefinitionResult && typeDefinitionResult instanceof Array && typeDefinitionResult.length != 0) {
335
+ // use documentSymbol instead of hover.
336
+ // this prevents type alias "squashing" done by tsserver.
337
+ // this also allows for grabbing the entire definition range and not just the symbol range.
338
+ const documentSymbolResult = await c.documentSymbol({
339
+ textDocument: {
340
+ uri: typeDefinitionResult[0].uri
341
+ }
342
+ });
343
+ // grab if the line number of typeDefinitionResult and documentSymbolResult matches
344
+ const dsMap = documentSymbolResult.reduce((m, obj) => {
345
+ m.set(obj.location.range.start.line, obj.location.range);
346
+ return m;
347
+ }, new Map());
348
+ const matchingSymbolRange = dsMap.get(typeDefinitionResult[0].range.start.line);
349
+ if (matchingSymbolRange) {
350
+ const snippetInRange = (0, utils_js_1.extractSnippet)(fs.readFileSync(typeDefinitionResult[0].uri.slice(7)).toString("utf8"), matchingSymbolRange.start, matchingSymbolRange.end);
351
+ const typeContext = getTypeContext(snippetInRange);
352
+ const formattedTypeSpan = (0, utils_js_1.formatTypeSpan)(snippetInRange);
353
+ await extractRelevantTypes(c, snippetInRange, typeContext.typeName, formattedTypeSpan, typeDefinitionResult[0].range.start.line, typeDefinitionResult[0].range.end.character + 2, foundSoFar, typeDefinitionResult[0].uri, outputFile, depth + 1);
354
+ }
355
+ // // try hover on the goto result
356
+ // const hoverResult = await c.hover({
357
+ // textDocument: {
358
+ // uri: (typeDefinitionResult[0] as Location).uri
359
+ // },
360
+ // position: {
361
+ // character: (typeDefinitionResult[0] as Location).range.start.character,
362
+ // line: (typeDefinitionResult[0] as Location).range.start.line
363
+ // }
364
+ // });
365
+ // // console.log("hoverResult: ", hoverResult)
366
+ //
367
+ // if (hoverResult != null) {
368
+ // console.log(`${JSON.stringify(typeDefinitionResult)}\n${JSON.stringify(hoverResult)}\n`);
369
+ // const formattedHoverResult = (hoverResult.contents as MarkupContent).value.split("\n").reduce((acc, curr) => {
370
+ // if (curr != "" && curr != "```typescript" && curr != "```") {
371
+ // return acc + curr;
372
+ // } else {
373
+ // return acc;
374
+ // }
375
+ // }, "");
376
+ //
377
+ // const typeContext = getTypeContext(formattedHoverResult);
378
+ // // console.log("typeContext: ", typeContext);
379
+ //
380
+ // // TODO:
381
+ // // This could be buggy if there are multi-line type signatures.
382
+ // // Because hover returns a formatted type signature, it could also include newlines.
383
+ // // This means that iterating over typeSpan.length might crash if it steps off the edge.
384
+ //
385
+ // const formattedTypeSpan = formatTypeSpan(typeContext!.typeSpan);
386
+ // console.log(`opt 2: ${formattedHoverResult}\n${typeContext}\n${formattedTypeSpan}`)
387
+ //
388
+ // await extractRelevantTypes(
389
+ // c,
390
+ // formattedHoverResult,
391
+ // typeContext!.typeName,
392
+ // formattedTypeSpan,
393
+ // (typeDefinitionResult[0] as Location).range.start.line,
394
+ // (typeDefinitionResult[0] as Location).range.end.character + 2,
395
+ // foundSoFar,
396
+ // (typeDefinitionResult[0] as Location).uri, outputFile, depth + 1);
397
+ // }
398
+ }
399
+ else {
400
+ }
401
+ }
402
+ catch (err) {
403
+ console.log(`${err}`);
404
+ }
405
+ }
406
+ }
407
+ return foundSoFar;
408
+ };
409
+ exports.extractRelevantTypes = extractRelevantTypes;
410
+ // return a list relevant context
411
+ // this would be akin to a LSP completion menu, but better
412
+ // filter the typing context for values whose types stand in a certain relation to these target types
413
+ // assign scores to each element of the resulting list, and return the prefix of that list truncated at some scoring and length thresholds
414
+ const extractRelevantHeaders = (preludeContent, relevantTypes, holeType) => {
415
+ // TODO:
416
+ // assign scores to each element of the resulting list, and return const ts = require('typescript');
417
+ // console.log(`\n\nrelevantTypes: ${[...relevantTypes.entries()]}\n`)
418
+ const relevantContext = new Set();
419
+ const targetTypes = generateTargetTypes(relevantTypes, holeType);
420
+ // only consider lines that start with let or const
421
+ const filteredLines = preludeContent.split("\n").filter((line) => {
422
+ return line.slice(0, 3) === "let" || line.slice(0, 5) === "const";
423
+ });
424
+ // check for relationship between each line and relevant types
425
+ filteredLines.forEach(line => {
426
+ const splittedLine = line.split(" = ")[0];
427
+ const typeSpanPattern = /(^[^:]*: )(.+)/;
428
+ const returnTypeSpan = splittedLine.match(typeSpanPattern)[2];
429
+ if (!(0, utils_js_1.isPrimitive)(returnTypeSpan.split(" => ")[1])) {
430
+ extractRelevantHeadersHelper(returnTypeSpan, targetTypes, relevantTypes, relevantContext, splittedLine);
431
+ }
432
+ });
433
+ return Array.from(relevantContext);
434
+ };
435
+ exports.extractRelevantHeaders = extractRelevantHeaders;
436
+ const generateTargetTypes = (relevantTypes, holeType) => {
437
+ const targetTypes = new Set();
438
+ targetTypes.add(holeType);
439
+ getTargetTypesHelper(relevantTypes, holeType, targetTypes);
440
+ return targetTypes;
441
+ };
442
+ const getTargetTypesHelper = (relevantTypes, currType, targetTypes) => {
443
+ // console.log("===Helper===")
444
+ if ((0, utils_js_1.isFunction)(currType)) {
445
+ const functionPattern = /(\(.+\))( => )(.+)(;*)/;
446
+ const rettype = currType.match(functionPattern)[3];
447
+ targetTypes.add(rettype);
448
+ getTargetTypesHelper(relevantTypes, rettype, targetTypes);
449
+ }
450
+ else if ((0, utils_js_1.isTuple)(currType)) {
451
+ const elements = (0, utils_js_1.parseTypeArrayString)(currType);
452
+ elements.forEach(element => {
453
+ targetTypes.add(element);
454
+ getTargetTypesHelper(relevantTypes, element, targetTypes);
455
+ });
456
+ }
457
+ // else if (isArray(currType)) {
458
+ // const elementType = currType.split("[]")[0];
459
+ //
460
+ // targetTypes.add(elementType)
461
+ // getTargetTypesHelper(relevantTypes, elementType, targetTypes);
462
+ // }
463
+ else {
464
+ if (relevantTypes.has(currType)) {
465
+ const definition = relevantTypes.get(currType).split(" = ")[1];
466
+ getTargetTypesHelper(relevantTypes, definition, targetTypes);
467
+ }
468
+ }
469
+ };
470
+ // resursive helper for extractRelevantContext
471
+ // checks for nested type equivalence
472
+ const extractRelevantHeadersHelper = (typeSpan, targetTypes, relevantTypes, relevantContext, line) => {
473
+ targetTypes.forEach(typ => {
474
+ if (isTypeEquivalent(typeSpan, typ, relevantTypes)) {
475
+ relevantContext.add(line);
476
+ }
477
+ if ((0, utils_js_1.isFunction)(typeSpan)) {
478
+ const functionPattern = /(\(.+\))( => )(.+)/;
479
+ const rettype = typeSpan.match(functionPattern)[3];
480
+ extractRelevantHeadersHelper(rettype, targetTypes, relevantTypes, relevantContext, line);
481
+ }
482
+ else if ((0, utils_js_1.isTuple)(typeSpan)) {
483
+ const elements = (0, utils_js_1.parseTypeArrayString)(typeSpan);
484
+ // const elements = typeSpan.slice(1, typeSpan.length - 1).split(", ");
485
+ elements.forEach(element => {
486
+ extractRelevantHeadersHelper(element, targetTypes, relevantTypes, relevantContext, line);
487
+ });
488
+ }
489
+ // else if (isUnion(typeSpan)) {
490
+ // const elements = typeSpan.split(" | ");
491
+ //
492
+ // elements.forEach(element => {
493
+ // extractRelevantContextHelper(element, relevantTypes, relevantContext, line);
494
+ // });
495
+ //
496
+ // else if (isArray(typeSpan)) {
497
+ // const elementType = typeSpan.split("[]")[0];
498
+ //
499
+ // if (isTypeEquivalent(elementType, typ, relevantTypes)) {
500
+ // extractRelevantContextHelper(elementType, targetTypes, relevantTypes, relevantContext, line);
501
+ // }
502
+ // }
503
+ });
504
+ };
505
+ // two types are equivalent if they have the same normal forms
506
+ const isTypeEquivalent = (t1, t2, relevantTypes) => {
507
+ const normT1 = normalize(t1, relevantTypes);
508
+ const normT2 = normalize(t2, relevantTypes);
509
+ return normT1 === normT2;
510
+ };
511
+ // return the normal form given a type span and a set of relevant types
512
+ // TODO: replace type checking with information from the AST?
513
+ const normalize = (typeSpan, relevantTypes) => {
514
+ var _a;
515
+ let normalForm = "";
516
+ // pattern matching for typeSpan
517
+ if ((0, utils_js_1.isPrimitive)(typeSpan)) {
518
+ return typeSpan;
519
+ }
520
+ else if ((0, utils_js_1.isObject)(typeSpan)) {
521
+ const elements = typeSpan.slice(1, typeSpan.length - 2).split(";");
522
+ normalForm += "{";
523
+ elements.forEach(element => {
524
+ if (element !== "") {
525
+ const kv = element.split(": ");
526
+ normalForm += kv[0].slice(1, kv[0].length), ": ", normalize(kv[1], relevantTypes);
527
+ normalForm += "; ";
528
+ }
529
+ });
530
+ normalForm += "}";
531
+ return normalForm;
532
+ }
533
+ else if ((0, utils_js_1.isTuple)(typeSpan)) {
534
+ // const elements = typeSpan.slice(1, typeSpan.length - 1).split(", ");
535
+ const elements = (0, utils_js_1.parseTypeArrayString)(typeSpan);
536
+ normalForm += "[";
537
+ elements.forEach((element, i) => {
538
+ normalForm += normalize(element, relevantTypes);
539
+ if (i < elements.length - 1) {
540
+ normalForm += ", ";
541
+ }
542
+ });
543
+ normalForm += "]";
544
+ return normalForm;
545
+ }
546
+ else if ((0, utils_js_1.isUnion)(typeSpan)) {
547
+ const elements = typeSpan.split(" | ");
548
+ elements.forEach((element, i) => {
549
+ normalForm += "(";
550
+ normalForm += normalize(element, relevantTypes);
551
+ normalForm += ")";
552
+ if (i < elements.length - 1) {
553
+ normalForm += " | ";
554
+ }
555
+ });
556
+ return normalForm;
557
+ }
558
+ else if ((0, utils_js_1.isArray)(typeSpan)) {
559
+ const element = typeSpan.split("[]")[0];
560
+ normalForm += normalize(element, relevantTypes);
561
+ normalForm += "[]";
562
+ return normalForm;
563
+ }
564
+ else if ((0, utils_js_1.isTypeAlias)(typeSpan)) {
565
+ const typ = (_a = relevantTypes.get(typeSpan)) === null || _a === void 0 ? void 0 : _a.split(" = ")[1];
566
+ if (typ === undefined) {
567
+ return typeSpan;
568
+ }
569
+ normalForm += normalize(typ, relevantTypes);
570
+ return normalForm;
571
+ }
572
+ else {
573
+ return typeSpan;
574
+ }
575
+ };
576
+ exports.normalize = normalize;
@@ -0,0 +1,2 @@
1
+ export { extractContext } from "./main";
2
+ export { completeWithLLM } from "./main";