@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.
@@ -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";