@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.
- package/dist/app.d.ts +27 -0
- package/dist/app.js +284 -0
- package/dist/codeql.d.ts +17 -0
- package/dist/codeql.js +1341 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.js +62 -0
- package/dist/core.d.ts +20 -0
- package/dist/core.js +576 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/main.d.ts +13 -0
- package/dist/main.js +254 -0
- package/dist/ocaml-driver.d.ts +30 -0
- package/dist/ocaml-driver.js +394 -0
- package/dist/ocaml-type-checker.d.ts +52 -0
- package/dist/ocaml-type-checker.js +286 -0
- package/dist/runner.d.ts +1 -0
- package/dist/runner.js +52 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.js +14 -0
- package/dist/typescript-driver.d.ts +27 -0
- package/dist/typescript-driver.js +542 -0
- package/dist/typescript-type-checker.d.ts +64 -0
- package/dist/typescript-type-checker.js +512 -0
- package/dist/utils.d.ts +40 -0
- package/dist/utils.js +350 -0
- package/package.json +1 -1
@@ -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;
|
package/dist/index.d.ts
ADDED