@jpoly1219/context-extractor 0.2.0 → 0.2.2

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/codeql.js ADDED
@@ -0,0 +1,1341 @@
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.getRelevantHeaders4 = exports.getRelevantHeaders3 = exports.getRelevantHeaders = exports.extractTypesAndLocations = exports.extractRelevantContextWithCodeQL = exports.extractHeadersWithCodeQL = exports.extractRelevantTypesWithCodeQL = exports.extractHoleType = exports.createDatabaseWithCodeQL = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const path = __importStar(require("path"));
29
+ const child_process_1 = require("child_process");
30
+ const utils_1 = require("./utils");
31
+ const constants_1 = require("./constants");
32
+ // import { CODEQL_PATH, ROOT_DIR, QUERY_DIR, BOOKING_DIR } from "./constants";
33
+ const createDatabaseWithCodeQL = (pathToCodeQL, targetPath) => {
34
+ const databaseName = path.basename(targetPath).concat("db");
35
+ const pathToDatabase = path.join(targetPath, databaseName);
36
+ try {
37
+ (0, child_process_1.execSync)(`${pathToCodeQL} database create ${pathToDatabase} --source-root=${targetPath} --overwrite --language=javascript-typescript 1> ${path.join(constants_1.ROOT_DIR, "codeql-out", `${path.basename(targetPath)}-codeql-out.txt`)} 2> ${path.join(constants_1.ROOT_DIR, "codeql-out", `${path.basename(targetPath)}-codeql-err.txt`)}`);
38
+ return pathToDatabase;
39
+ }
40
+ catch (err) {
41
+ console.error(`error while creating database: ${err}`);
42
+ throw err;
43
+ }
44
+ };
45
+ exports.createDatabaseWithCodeQL = createDatabaseWithCodeQL;
46
+ const extractHoleType = (pathToCodeQL, pathToQuery, pathToDatabase, outDir) => {
47
+ const q = createHoleTypeQuery();
48
+ fs.writeFileSync(pathToQuery, q);
49
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
50
+ // console.log("extractHoleType q res: ", queryRes)
51
+ return queryRes[0];
52
+ };
53
+ exports.extractHoleType = extractHoleType;
54
+ const extractRelevantTypesWithCodeQL = (pathToCodeQL, pathToQuery, pathToDatabase, outDir) => {
55
+ const pathToBqrs = path.join(outDir, "relevant-types.bqrs");
56
+ const pathToDecodedJSON = path.join(outDir, "relevant-types.json");
57
+ // run CodeQL query relevant-types.ql
58
+ try {
59
+ (0, child_process_1.execSync)(`${pathToCodeQL} query run ${pathToQuery} --database=${pathToDatabase} --output=${pathToBqrs}`);
60
+ }
61
+ catch (err) {
62
+ console.error(`error while running query ${pathToQuery}: ${err}`);
63
+ }
64
+ try {
65
+ (0, child_process_1.execSync)(`${pathToCodeQL} bqrs decode ${pathToBqrs} --format=json --output=${pathToDecodedJSON} --no-titles`);
66
+ }
67
+ catch (err) {
68
+ console.error(`error while trying to decode ${outDir}/relevant-types.bqrs: ${err}`);
69
+ }
70
+ const relevantTypesContent = fs.readFileSync(pathToDecodedJSON);
71
+ const relevantTypes = (0, utils_1.parseCodeQLRelevantTypes)(JSON.parse(relevantTypesContent.toString()));
72
+ // return relevantTypes;
73
+ // return Array.from(relevantTypes, ([_, v]) => { return v.typeAliasDeclaration });
74
+ return relevantTypes;
75
+ };
76
+ exports.extractRelevantTypesWithCodeQL = extractRelevantTypesWithCodeQL;
77
+ const extractHeadersWithCodeQL = (pathToCodeQL, pathToQuery, pathToDatabase, outDir) => {
78
+ const pathToBqrs = path.join(outDir, "vars.bqrs");
79
+ const pathToDecodedJSON = path.join(outDir, "vars.json");
80
+ // run CodeQL query vars.ql
81
+ try {
82
+ (0, child_process_1.execSync)(`${pathToCodeQL} query run ${pathToQuery} --database=${pathToDatabase} --output=${pathToBqrs}`);
83
+ }
84
+ catch (err) {
85
+ console.error(`error while running query ${pathToQuery}: ${err}`);
86
+ }
87
+ try {
88
+ (0, child_process_1.execSync)(`${pathToCodeQL} bqrs decode ${pathToBqrs} --format=json --output=${pathToDecodedJSON} --no-titles`);
89
+ }
90
+ catch (err) {
91
+ console.error(`error while trying to decode ${outDir}/vars.bqrs: ${err}`);
92
+ }
93
+ const varsContent = fs.readFileSync(pathToDecodedJSON);
94
+ const vars = (0, utils_1.parseCodeQLVars)(JSON.parse(varsContent.toString()));
95
+ return vars;
96
+ };
97
+ exports.extractHeadersWithCodeQL = extractHeadersWithCodeQL;
98
+ const extractTypes = (pathToCodeQL, pathToQuery, pathToDatabase, outDir) => {
99
+ // console.log("==extractTypes==")
100
+ const pathToBqrs = path.join(outDir, "types.bqrs");
101
+ const pathToDecodedJSON = path.join(outDir, "types.json");
102
+ // run CodeQL query types.ql
103
+ try {
104
+ (0, child_process_1.execSync)(`${pathToCodeQL} query run ${pathToQuery} --database=${pathToDatabase} --output=${pathToBqrs}`);
105
+ }
106
+ catch (err) {
107
+ console.error(`error while running query ${pathToQuery}: ${err}`);
108
+ }
109
+ try {
110
+ (0, child_process_1.execSync)(`${pathToCodeQL} bqrs decode ${pathToBqrs} --format=json --output=${pathToDecodedJSON} --no-titles`);
111
+ }
112
+ catch (err) {
113
+ console.error(`error while trying to decode ${outDir}/types.bqrs: ${err}`);
114
+ }
115
+ const typesContent = fs.readFileSync(pathToDecodedJSON);
116
+ const types = (0, utils_1.parseCodeQLTypes)(JSON.parse(typesContent.toString()));
117
+ // console.log("extractTypes result: ", types, "\n\n")
118
+ return types;
119
+ };
120
+ const extractTypesAndLocations = (pathToCodeQL, pathToQuery, pathToDatabase, outDir) => {
121
+ const pathToBqrs = path.join(outDir, "imports.bqrs");
122
+ const pathToDecodedJSON = path.join(outDir, "imports.json");
123
+ try {
124
+ (0, child_process_1.execSync)(`${pathToCodeQL} query run ${pathToQuery} --database=${pathToDatabase} --output=${pathToBqrs}`);
125
+ }
126
+ catch (err) {
127
+ console.error(`error while running query ${pathToQuery}: ${err}`);
128
+ }
129
+ try {
130
+ (0, child_process_1.execSync)(`${pathToCodeQL} bqrs decode ${pathToBqrs} --format=json --output=${pathToDecodedJSON} --no-titles`);
131
+ }
132
+ catch (err) {
133
+ console.error(`error while trying to decode ${outDir}/imports.bqrs: ${err}`);
134
+ }
135
+ const typesAndLocationsContent = fs.readFileSync(pathToDecodedJSON);
136
+ const locationsAndTypes = (0, utils_1.parseCodeQLLocationsAndTypes)(JSON.parse(typesAndLocationsContent.toString()));
137
+ const typesAndLocations = (0, utils_1.parseCodeQLTypesAndLocations)(JSON.parse(typesAndLocationsContent.toString()));
138
+ return { locationToType: locationsAndTypes, typeToLocation: typesAndLocations };
139
+ };
140
+ exports.extractTypesAndLocations = extractTypesAndLocations;
141
+ const extractRelevantContextWithCodeQL = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, headers, relevantTypes) => {
142
+ // console.log("==entry==")
143
+ // console.log(Date.now())
144
+ // console.log("extractRelevantContextWithCodeQL start: ", Date.now())
145
+ const relevantContext = new Set();
146
+ const knownNormalForms = new Map();
147
+ // for each var in vars, check if its type is equivalent to any of relevantTypes
148
+ headers.forEach((header) => {
149
+ // console.log("\n\nheader: ", header, "\n\n")
150
+ const typeOfHeader = { typeName: header.typeAnnotation, typeQLClass: header.typeQLClass };
151
+ const isEquivalent = extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, typeOfHeader, relevantTypes, knownNormalForms);
152
+ if (isEquivalent) {
153
+ relevantContext.add(header.constDeclaration);
154
+ }
155
+ });
156
+ // console.log("knownNormalForms: ", knownNormalForms)
157
+ // console.log("extractRelevantContextWithCodeQL end: ", Date.now())
158
+ return relevantContext;
159
+ };
160
+ exports.extractRelevantContextWithCodeQL = extractRelevantContextWithCodeQL;
161
+ const extractRelevantContextHelper = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, headerType, relevantTypes, knownNormalForms) => {
162
+ // console.log("\n\n==recurse==")
163
+ // console.log("headerType: ", headerType)
164
+ // NOTE:
165
+ // extract types that are consistent to any of the target types
166
+ // extract functions whose return types are equivalent to any of the target types
167
+ // extract products whose component types are equivalent to any of the target types
168
+ for (const [key, typ] of relevantTypes.entries()) {
169
+ const typObj = { typeName: typ.typeDefinition, typeQLClass: typ.typeQLClass };
170
+ // console.log("typ: ", typ)
171
+ if (isTypeEquivalent(pathToCodeQL, pathToQuery, pathToDatabase, outDir, headerType, typObj, relevantTypes, knownNormalForms)) {
172
+ // console.log("isTypeEquivalent!")
173
+ return true;
174
+ }
175
+ }
176
+ // if (isQLPredefined(headerType.typeQLClass) || isQLLiteral(headerType.typeQLClass) || isQLKeyword(headerType.typeQLClass)) {
177
+ // return;
178
+ //
179
+ // }
180
+ if ((0, utils_1.isQLFunction)(headerType.typeQLClass)) {
181
+ const q = createReturnTypeQuery(headerType.typeName);
182
+ // console.log("extractor fq: ", q)
183
+ fs.writeFileSync(pathToQuery, q);
184
+ // could use extractVars
185
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
186
+ // console.log("extractor fq res: ", queryRes)
187
+ return extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, knownNormalForms);
188
+ }
189
+ else if ((0, utils_1.isQLInterface)(headerType.typeQLClass)) {
190
+ const q = createInterfaceComponentsTypeQuery(headerType.typeName);
191
+ // console.log("extractor iq", q)
192
+ fs.writeFileSync(pathToQuery, q);
193
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
194
+ // console.log("extractor iq res", queryRes)
195
+ queryRes.forEach(obj => {
196
+ const val = obj.typeName.split(":")[1];
197
+ const typObj = { typeName: val, typeQLClass: obj.typeQLClass };
198
+ return extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, typObj, relevantTypes, knownNormalForms);
199
+ });
200
+ }
201
+ else if ((0, utils_1.isQLTuple)(headerType.typeQLClass)) {
202
+ const q = createTupleComponentsTypeQuery(headerType.typeName);
203
+ // console.log("extractor tq", q)
204
+ fs.writeFileSync(pathToQuery, q);
205
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
206
+ // console.log("extractor tq res", queryRes)
207
+ let res = true;
208
+ queryRes.forEach(obj => {
209
+ res && (res = extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes, knownNormalForms));
210
+ });
211
+ return res;
212
+ }
213
+ else if ((0, utils_1.isQLUnion)(headerType.typeQLClass)) {
214
+ const q = createUnionComponentsTypeQuery(headerType.typeName);
215
+ // console.log("extractor uq", q)
216
+ fs.writeFileSync(pathToQuery, q);
217
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
218
+ // console.log("extractor uq res", queryRes)
219
+ let res = true;
220
+ queryRes.forEach(obj => {
221
+ res && (res = extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes, knownNormalForms));
222
+ });
223
+ return res;
224
+ }
225
+ else if ((0, utils_1.isQLArray)(headerType.typeQLClass)) {
226
+ const q = createArrayTypeQuery(headerType.typeName);
227
+ // console.log("extractor aq", q)
228
+ fs.writeFileSync(pathToQuery, q);
229
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
230
+ // console.log("extractor aq res", queryRes)
231
+ return extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, knownNormalForms);
232
+ // if (isTypeEquivalent(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], typObj, relevantTypes)) {
233
+ // extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, relevantContext);
234
+ // }
235
+ }
236
+ else if ((0, utils_1.isQLLocalTypeAccess)(headerType.typeQLClass)) {
237
+ const q = createLocalTypeAccessTypeQuery(headerType.typeName);
238
+ // console.log("extractor ltaq", q)
239
+ fs.writeFileSync(pathToQuery, q);
240
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
241
+ // console.log("extractor ltaq res", queryRes)
242
+ return extractRelevantContextHelper(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, knownNormalForms);
243
+ }
244
+ else {
245
+ // console.log(`extractRelevantContextHelper: this doesn't exist: ${JSON.stringify(headerType)}`);
246
+ // console.error(`extractRelevantContextHelper: this doesn't exist: ${JSON.stringify(headerType)}`);
247
+ // throw Error(`extractRelevantContextHelper: this doesn't exist: ${JSON.stringify(headerType)}`);
248
+ }
249
+ // console.log("not found for header: ", headerType)
250
+ return false;
251
+ };
252
+ const isTypeEquivalent = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, t1, t2, relevantTypes, knownNormalForms) => {
253
+ // console.log("\n\n==isTypeEquivalent==")
254
+ // TODO: the headerType.typeName will include all the arg names too, for example (model: Model, user: User) => Booking[]
255
+ if (knownNormalForms.has(t1.typeName) && knownNormalForms.has(t2.typeName)) {
256
+ const normT1 = knownNormalForms.get(t1.typeName);
257
+ const normT2 = knownNormalForms.get(t2.typeName);
258
+ // console.log("\n\nnormal forms:\n", t1, " -> ", normT1, ", ", t2, " -> ", normT2, "\n\n")
259
+ return normT1 === normT2;
260
+ }
261
+ else if (knownNormalForms.has(t1.typeName)) {
262
+ const normT1 = knownNormalForms.get(t1.typeName);
263
+ const normT2 = normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, t2, relevantTypes, knownNormalForms);
264
+ knownNormalForms.set(t2.typeName, normT2);
265
+ // console.log("\n\nnormal forms:\n", t1, " -> ", normT1, ", ", t2, " -> ", normT2, "\n\n")
266
+ return normT1 === normT2;
267
+ }
268
+ else if (knownNormalForms.has(t2.typeName)) {
269
+ const normT1 = normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, t1, relevantTypes, knownNormalForms);
270
+ knownNormalForms.set(t1.typeName, normT1);
271
+ const normT2 = knownNormalForms.get(t2.typeName);
272
+ // console.log("\n\nnormal forms:\n", t1, " -> ", normT1, ", ", t2, " -> ", normT2, "\n\n")
273
+ return normT1 === normT2;
274
+ }
275
+ else {
276
+ const normT1 = normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, t1, relevantTypes, knownNormalForms);
277
+ const normT2 = normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, t2, relevantTypes, knownNormalForms);
278
+ knownNormalForms.set(t1.typeName, normT1);
279
+ knownNormalForms.set(t2.typeName, normT1);
280
+ // console.log("\n\nnormal forms:\n", t1, " -> ", normT1, ", ", t2, " -> ", normT2, "\n\n")
281
+ return normT1 === normT2;
282
+ }
283
+ // TODO: speed this up by saving known normal forms
284
+ };
285
+ const normalize = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, typeSpan, relevantTypes, knownNormalForms) => {
286
+ // console.log("==normalize==")
287
+ // console.log("typespan: ", typeSpan)
288
+ // if the type is in relevant types, use that instead
289
+ // if (relevantTypes.has(typeSpan.typeName)) {
290
+ // const obj: typesObject = { typeName: relevantTypes.get(typeSpan.typeName)!.typeDefinition, typeQLClass: relevantTypes.get(typeSpan.typeName)!.typeQLClass };
291
+ // return normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes);
292
+ // return typeSpan.typeName;
293
+ // }
294
+ // if not, run a query to find the type definition
295
+ if ((0, utils_1.isQLPredefined)(typeSpan.typeQLClass) || (0, utils_1.isQLLiteral)(typeSpan.typeQLClass) || (0, utils_1.isQLKeyword)(typeSpan.typeQLClass)) {
296
+ knownNormalForms.set(typeSpan.typeName, typeSpan.typeName);
297
+ return typeSpan.typeName;
298
+ }
299
+ else if ((0, utils_1.isQLFunction)(typeSpan.typeQLClass)) {
300
+ // TODO: the headerType.typeName will include all the arg names too, for example (model: Model, user: User) => Booking[]
301
+ // the normal form will only include (Model, User) => Booking[]
302
+ // query for argument types and return types
303
+ // then concat them using "(" + normalize(argType) + ... + ") => " + normalize(returnType)
304
+ // adding a normal form may suffer from this phenomenon, as two functions of same arg types and return type with different arg names will fail to check for existance
305
+ // make a check if it's a function
306
+ const aq = createArgTypeQuery(typeSpan.typeName);
307
+ fs.writeFileSync(pathToQuery, aq);
308
+ const aqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
309
+ // console.log("normalize faq res: ", aqQueryRes)
310
+ const rq = createReturnTypeQuery(typeSpan.typeName);
311
+ fs.writeFileSync(pathToQuery, rq);
312
+ const rqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
313
+ // console.log("normalize frq res: ", rqQueryRes)
314
+ const normalFormBuilder = [];
315
+ normalFormBuilder.push("(");
316
+ aqQueryRes.forEach((obj, i) => {
317
+ normalFormBuilder.push(normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes, knownNormalForms));
318
+ if (i < aqQueryRes.length - 1) {
319
+ normalFormBuilder.push(", ");
320
+ }
321
+ });
322
+ normalFormBuilder.push(") => ");
323
+ normalFormBuilder.push(normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, rqQueryRes[0], relevantTypes, knownNormalForms));
324
+ const normalForm = normalFormBuilder.join("");
325
+ knownNormalForms.set(typeSpan.typeName, normalForm);
326
+ return normalForm;
327
+ }
328
+ else if ((0, utils_1.isQLInterface)(typeSpan.typeQLClass)) {
329
+ const q = createInterfaceComponentsTypeQuery(typeSpan.typeName);
330
+ // console.log("normalize iq: ", q)
331
+ fs.writeFileSync(pathToQuery, q);
332
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
333
+ // console.log("normalize iq res: ", queryRes)
334
+ const normalFormBuilder = [];
335
+ normalFormBuilder.push("{");
336
+ queryRes.forEach((obj, i) => {
337
+ const key = obj.typeName.split(": ")[0];
338
+ const val = obj.typeName.split(": ")[1];
339
+ normalFormBuilder.push("".concat(key, ": ", normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: val, typeQLClass: obj.typeQLClass }, relevantTypes, knownNormalForms)));
340
+ if (i < queryRes.length - 1) {
341
+ normalFormBuilder.push("; ");
342
+ }
343
+ else {
344
+ normalFormBuilder.push(" ");
345
+ }
346
+ });
347
+ normalFormBuilder.push("}");
348
+ const normalForm = normalFormBuilder.join("");
349
+ knownNormalForms.set(typeSpan.typeName, normalForm);
350
+ return normalForm;
351
+ }
352
+ else if ((0, utils_1.isQLTuple)(typeSpan.typeQLClass)) {
353
+ const q = createTupleComponentsTypeQuery(typeSpan.typeName);
354
+ // console.log("normalize tq: ", q)
355
+ fs.writeFileSync(pathToQuery, q);
356
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
357
+ // console.log("normalize tq res: ", queryRes)
358
+ const normalFormBuilder = [];
359
+ normalFormBuilder.push("[");
360
+ queryRes.forEach((obj, i) => {
361
+ normalFormBuilder.push(normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes, knownNormalForms));
362
+ if (i < queryRes.length - 1) {
363
+ normalFormBuilder.push(", ");
364
+ }
365
+ });
366
+ normalFormBuilder.push("]");
367
+ const normalForm = normalFormBuilder.join("");
368
+ knownNormalForms.set(typeSpan.typeName, normalForm);
369
+ return normalForm;
370
+ }
371
+ else if ((0, utils_1.isQLUnion)(typeSpan.typeQLClass)) {
372
+ const q = createUnionComponentsTypeQuery(typeSpan.typeName);
373
+ // console.log("normalize uq: ", q)
374
+ fs.writeFileSync(pathToQuery, q);
375
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
376
+ // console.log("normalize uq res: ", queryRes)
377
+ const normalFormBuilder = [];
378
+ queryRes.forEach((obj, i) => {
379
+ normalFormBuilder.push("".concat(normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, relevantTypes, knownNormalForms)));
380
+ if (i < queryRes.length - 1) {
381
+ normalFormBuilder.push(" | ");
382
+ }
383
+ });
384
+ const normalForm = normalFormBuilder.join("");
385
+ knownNormalForms.set(typeSpan.typeName, normalForm);
386
+ return normalForm;
387
+ }
388
+ else if ((0, utils_1.isQLArray)(typeSpan.typeQLClass)) {
389
+ const q = createArrayTypeQuery(typeSpan.typeName);
390
+ // console.log("normalize aq: ", q)
391
+ fs.writeFileSync(pathToQuery, q);
392
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
393
+ // console.log("normalize aq res: ", queryRes)
394
+ const normalForm = "".concat(normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, knownNormalForms), "[]");
395
+ knownNormalForms.set(typeSpan.typeName, normalForm);
396
+ return normalForm;
397
+ }
398
+ else if ((0, utils_1.isQLLocalTypeAccess)(typeSpan.typeQLClass)) {
399
+ const q = createLocalTypeAccessTypeQuery(typeSpan.typeName);
400
+ // console.log("normalize ltaq: ", q)
401
+ fs.writeFileSync(pathToQuery, q);
402
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
403
+ // console.log("normalize ltaq res: ", queryRes)
404
+ const normalForm = normalize(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], relevantTypes, knownNormalForms);
405
+ knownNormalForms.set(typeSpan.typeName, normalForm);
406
+ return normalForm;
407
+ }
408
+ else {
409
+ // console.log(`normalize: this doesn't exist: ${JSON.stringify(typeSpan)}`)
410
+ console.error(`normalize: this doesn't exist: ${JSON.stringify(typeSpan)}`);
411
+ throw Error(`normalize: this doesn't exist: ${JSON.stringify(typeSpan)}`);
412
+ }
413
+ };
414
+ // TODO:
415
+ // make a target type generator.
416
+ // the below method works, but it could be very inefficient.
417
+ // get the hole function type
418
+ // get the argument type
419
+ // get the return type
420
+ // keep the skeleton (...) => ...
421
+ // use codeql to recurse into each argument type and return type
422
+ // most normal form: (normalize(arg1), normalize(arg2), ...) => normalize(ret)
423
+ // save normalize(arg1), normalize(arg2), ..., normalize(ret), and every recursive layer
424
+ // each could be saved in an array, where the array holds all forms arg1 could take.
425
+ // type of the hole itself: (norm(a1), ...) => norm(ret)
426
+ // type of the return: norm(ret)
427
+ // type of the product: (norm(a1), ...)
428
+ // type of the components: norm(a1), norm(a2), ...
429
+ // TODO:
430
+ // given a list of recursively looked up target types, for each header,
431
+ // is the header type in the list?
432
+ // if header is a function, is the return type in the list?
433
+ // else, is norm(ret) in the list?
434
+ // if header is a product, are any of the components in the list?
435
+ // else, are any of the norm(components) in the list?
436
+ // TODO:
437
+ // could there be a way to keep track of the layers of recursion?
438
+ const getRelevantHeaders = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, headers, holeType) => {
439
+ // console.log("getRelevantHeaders start: ", Date.now())
440
+ const obj = generateTargetTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType);
441
+ const targetTypes = obj.targetTypes;
442
+ const knownNormalForms = obj.knownNormalForms;
443
+ const relevantHeaders = new Set();
444
+ headers.forEach(header => {
445
+ // console.log("header: ", header)
446
+ if (targetTypes.has(header.typeAnnotation)) {
447
+ relevantHeaders.add(header.constDeclaration);
448
+ }
449
+ else if ((0, utils_1.isQLFunction)(header.typeQLClass)) {
450
+ const q = createReturnTypeQuery(header.typeAnnotation);
451
+ fs.writeFileSync(pathToQuery, q);
452
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
453
+ // console.log("header fq res: ", queryRes)
454
+ // NOTE: would be nice if we could "step" recursion into normalize2
455
+ // maybe make normalize2 a higher order function that returns a function that we can call
456
+ if (targetTypes.has(queryRes[0].typeName)) {
457
+ relevantHeaders.add(header.constDeclaration);
458
+ }
459
+ else if (targetTypes.has(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], targetTypes, knownNormalForms))) {
460
+ relevantHeaders.add(header.constDeclaration);
461
+ }
462
+ }
463
+ else if ((0, utils_1.isQLTuple)(header.typeQLClass)) {
464
+ const q = createTupleComponentsTypeQuery(header.typeAnnotation);
465
+ // console.log("header tq", q)
466
+ fs.writeFileSync(pathToQuery, q);
467
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
468
+ // console.log("header tq res", queryRes)
469
+ queryRes.forEach(obj => {
470
+ if (targetTypes.has(obj.typeName)) {
471
+ relevantHeaders.add(header.constDeclaration);
472
+ }
473
+ else if (targetTypes.has(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, targetTypes, knownNormalForms))) {
474
+ relevantHeaders.add(header.constDeclaration);
475
+ }
476
+ });
477
+ }
478
+ });
479
+ // console.log("getRelevantHeaders end: ", Date.now())
480
+ return relevantHeaders;
481
+ };
482
+ exports.getRelevantHeaders = getRelevantHeaders;
483
+ const generateTargetTypes = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType) => {
484
+ const targetTypes = new Set();
485
+ const knownNormalForms = new Map();
486
+ // console.log("generateTargetTypes start: ", Date.now())
487
+ normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType, targetTypes, knownNormalForms);
488
+ // console.log("generateTargetTypes end: ", Date.now())
489
+ // console.log("targetTypes: ", targetTypes)
490
+ // console.log("knownNormalForms: ", knownNormalForms)
491
+ return { targetTypes: targetTypes, knownNormalForms: knownNormalForms };
492
+ };
493
+ const normalize2 = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, typeSpan, targetTypes, knownNormalForms) => {
494
+ // console.log("==normalize2==")
495
+ // console.log("typespan: ", typeSpan)
496
+ if (knownNormalForms.has(typeSpan.typeName)) {
497
+ return knownNormalForms.get(typeSpan.typeName);
498
+ }
499
+ targetTypes.add(typeSpan.typeName);
500
+ if ((0, utils_1.isQLPredefined)(typeSpan.typeQLClass) || (0, utils_1.isQLLiteral)(typeSpan.typeQLClass) || (0, utils_1.isQLKeyword)(typeSpan.typeQLClass)) {
501
+ targetTypes.add(typeSpan.typeName);
502
+ return typeSpan.typeName;
503
+ }
504
+ else if ((0, utils_1.isQLFunction)(typeSpan.typeQLClass)) {
505
+ const aq = createArgTypeQuery(typeSpan.typeName);
506
+ fs.writeFileSync(pathToQuery, aq);
507
+ const aqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
508
+ // console.log("normalize faq res: ", aqQueryRes)
509
+ const rq = createReturnTypeQuery(typeSpan.typeName);
510
+ fs.writeFileSync(pathToQuery, rq);
511
+ const rqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
512
+ // console.log("normalize frq res: ", rqQueryRes)
513
+ const normalFormBuilder = [];
514
+ normalFormBuilder.push("(");
515
+ aqQueryRes.forEach((obj, i) => {
516
+ normalFormBuilder.push(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, targetTypes, knownNormalForms));
517
+ if (i < aqQueryRes.length - 1) {
518
+ normalFormBuilder.push(", ");
519
+ }
520
+ });
521
+ normalFormBuilder.push(") => ");
522
+ normalFormBuilder.push(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, rqQueryRes[0], targetTypes, knownNormalForms));
523
+ const normalForm = normalFormBuilder.join("");
524
+ targetTypes.add(normalForm);
525
+ knownNormalForms.set(typeSpan.typeName, normalForm);
526
+ return normalForm;
527
+ }
528
+ else if ((0, utils_1.isQLInterface)(typeSpan.typeQLClass)) {
529
+ const q = createInterfaceComponentsTypeQuery(typeSpan.typeName);
530
+ // console.log("normalize iq: ", q)
531
+ fs.writeFileSync(pathToQuery, q);
532
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
533
+ // console.log("normalize iq res: ", queryRes)
534
+ const normalFormBuilder = [];
535
+ normalFormBuilder.push("{");
536
+ queryRes.forEach((obj, i) => {
537
+ const key = obj.typeName.split(": ")[0];
538
+ const val = obj.typeName.split(": ")[1];
539
+ normalFormBuilder.push("".concat(" ", key, ": ", normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: val, typeQLClass: obj.typeQLClass }, targetTypes, knownNormalForms)));
540
+ if (i < queryRes.length - 1) {
541
+ normalFormBuilder.push("; ");
542
+ }
543
+ else {
544
+ normalFormBuilder.push(" ");
545
+ }
546
+ });
547
+ normalFormBuilder.push("}");
548
+ const normalForm = normalFormBuilder.join("");
549
+ targetTypes.add(normalForm);
550
+ knownNormalForms.set(typeSpan.typeName, normalForm);
551
+ return normalForm;
552
+ }
553
+ else if ((0, utils_1.isQLTuple)(typeSpan.typeQLClass)) {
554
+ const q = createTupleComponentsTypeQuery(typeSpan.typeName);
555
+ // console.log("normalize tq: ", q)
556
+ fs.writeFileSync(pathToQuery, q);
557
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
558
+ // console.log("normalize tq res: ", queryRes)
559
+ const normalFormBuilder = [];
560
+ normalFormBuilder.push("[");
561
+ queryRes.forEach((obj, i) => {
562
+ normalFormBuilder.push(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, targetTypes, knownNormalForms));
563
+ if (i < queryRes.length - 1) {
564
+ normalFormBuilder.push(", ");
565
+ }
566
+ });
567
+ normalFormBuilder.push("]");
568
+ const normalForm = normalFormBuilder.join("");
569
+ targetTypes.add(normalForm);
570
+ knownNormalForms.set(typeSpan.typeName, normalForm);
571
+ return normalForm;
572
+ }
573
+ else if ((0, utils_1.isQLUnion)(typeSpan.typeQLClass)) {
574
+ const q = createUnionComponentsTypeQuery(typeSpan.typeName);
575
+ // console.log("normalize uq: ", q)
576
+ fs.writeFileSync(pathToQuery, q);
577
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
578
+ // console.log("normalize uq res: ", queryRes)
579
+ const normalFormBuilder = [];
580
+ queryRes.forEach((obj, i) => {
581
+ normalFormBuilder.push(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, targetTypes, knownNormalForms));
582
+ if (i < queryRes.length - 1) {
583
+ normalFormBuilder.push(" | ");
584
+ }
585
+ });
586
+ const normalForm = normalFormBuilder.join("");
587
+ targetTypes.add(normalForm);
588
+ knownNormalForms.set(typeSpan.typeName, normalForm);
589
+ return normalForm;
590
+ }
591
+ else if ((0, utils_1.isQLArray)(typeSpan.typeQLClass)) {
592
+ const q = createArrayTypeQuery(typeSpan.typeName);
593
+ // console.log("normalize aq: ", q)
594
+ fs.writeFileSync(pathToQuery, q);
595
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
596
+ // console.log("normalize aq res: ", queryRes)
597
+ const normalForm = "".concat(normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], targetTypes, knownNormalForms), "[]");
598
+ targetTypes.add(normalForm);
599
+ knownNormalForms.set(typeSpan.typeName, normalForm);
600
+ return normalForm;
601
+ }
602
+ else if ((0, utils_1.isQLLocalTypeAccess)(typeSpan.typeQLClass)) {
603
+ const q = createLocalTypeAccessTypeQuery(typeSpan.typeName);
604
+ // console.log("normalize ltaq: ", q)
605
+ fs.writeFileSync(pathToQuery, q);
606
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
607
+ // console.log("normalize ltaq res: ", queryRes)
608
+ const normalForm = normalize2(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], targetTypes, knownNormalForms);
609
+ targetTypes.add(normalForm);
610
+ knownNormalForms.set(typeSpan.typeName, normalForm);
611
+ return normalForm;
612
+ }
613
+ else {
614
+ // console.log(`normalize2: this doesn't exist: ${JSON.stringify(typeSpan)}`)
615
+ console.error(`normalize2: this doesn't exist: ${JSON.stringify(typeSpan)}`);
616
+ throw Error(`normalize2: this doesn't exist: ${JSON.stringify(typeSpan)}`);
617
+ }
618
+ };
619
+ const getRelevantHeaders3 = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, headers, holeType, relevantTypes) => {
620
+ // console.log("getRelevantHeaders3 start: ", Date.now())
621
+ const obj = generateTargetTypes3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType, relevantTypes);
622
+ const targetTypes = obj.targetTypes;
623
+ const knownNormalForms = obj.knownNormalForms;
624
+ const relevantHeaders = new Set();
625
+ headers.forEach(header => {
626
+ if (targetTypes.has(header.typeAnnotation)) {
627
+ relevantHeaders.add(header.constDeclaration);
628
+ }
629
+ else if ((0, utils_1.isQLFunction)(header.typeQLClass)) {
630
+ // const q = createReturnTypeQuery(header.typeAnnotation);
631
+ // fs.writeFileSync(pathToQuery, q);
632
+ // const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
633
+ // console.log("header fq res: ", queryRes)
634
+ const returnType = header.components[0];
635
+ if (targetTypes.has(returnType.typeName)) {
636
+ relevantHeaders.add(header.constDeclaration);
637
+ }
638
+ else if (targetTypes.has(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: returnType.typeName, typeQLClass: returnType.typeQLClass }, relevantTypes, targetTypes, knownNormalForms))) {
639
+ relevantHeaders.add(header.constDeclaration);
640
+ }
641
+ }
642
+ else if ((0, utils_1.isQLTuple)(header.typeQLClass)) {
643
+ // const q = createTupleComponentsTypeQuery(header.typeAnnotation);
644
+ // console.log("header tq", q)
645
+ // fs.writeFileSync(pathToQuery, q);
646
+ // const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
647
+ // console.log("header tq res", queryRes)
648
+ const components = header.components;
649
+ components.forEach(obj => {
650
+ if (targetTypes.has(obj.typeName)) {
651
+ relevantHeaders.add(header.constDeclaration);
652
+ }
653
+ else if (targetTypes.has(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: obj.typeName, typeQLClass: obj.typeQLClass }, relevantTypes, targetTypes, knownNormalForms))) {
654
+ relevantHeaders.add(header.constDeclaration);
655
+ }
656
+ });
657
+ }
658
+ });
659
+ // console.log("getRelevantHeaders3 end: ", Date.now())
660
+ return relevantHeaders;
661
+ };
662
+ exports.getRelevantHeaders3 = getRelevantHeaders3;
663
+ const generateTargetTypes3 = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType, relevantTypes) => {
664
+ const targetTypes = new Set();
665
+ const knownNormalForms = new Map();
666
+ // console.log("generateTargetTypes3 start: ", Date.now())
667
+ normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, holeType, relevantTypes, targetTypes, knownNormalForms);
668
+ // console.log("generateTargetTypes3 end: ", Date.now())
669
+ // console.log("targetTypes: ", targetTypes)
670
+ // console.log("knownNormalForms: ", knownNormalForms)
671
+ return { targetTypes: targetTypes, knownNormalForms: knownNormalForms };
672
+ };
673
+ const normalize3 = (pathToCodeQL, pathToQuery, pathToDatabase, outDir, typ, knownTypes, targetTypes, knownNormalForms) => {
674
+ // console.log("current: ", typ)
675
+ // check if exists in known types
676
+ // if so, access and check its class
677
+ // depending on the class, build a normal form using recursion
678
+ if ((0, utils_1.isQLPredefined)(typ.typeQLClass) || (0, utils_1.isQLLiteral)(typ.typeQLClass) || (0, utils_1.isQLKeyword)(typ.typeQLClass)) {
679
+ targetTypes.add(typ.typeName);
680
+ return typ.typeName;
681
+ }
682
+ else if ((0, utils_1.isQLFunction)(typ.typeQLClass)) {
683
+ // NOTE: optimize for different arg name but same type
684
+ if (knownTypes.has(typ.typeName)) {
685
+ const definition = knownTypes.get(typ.typeName);
686
+ const components = definition.components;
687
+ const returnType = components[0];
688
+ const argumentTypes = components.slice(1, components.length);
689
+ const normalFormBuilder = [];
690
+ normalFormBuilder.push("(");
691
+ argumentTypes.forEach((argTyp, i) => {
692
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, argTyp, knownTypes, targetTypes, knownNormalForms));
693
+ if (i < argumentTypes.length - 1) {
694
+ normalFormBuilder.push(", ");
695
+ }
696
+ });
697
+ normalFormBuilder.push(") => ");
698
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, returnType, knownTypes, targetTypes, knownNormalForms));
699
+ const normalForm = normalFormBuilder.join("");
700
+ targetTypes.add(normalForm);
701
+ knownNormalForms.set(typ.typeName, normalForm);
702
+ return normalForm;
703
+ }
704
+ else {
705
+ const aq = createArgTypeQuery(typ.typeName);
706
+ fs.writeFileSync(pathToQuery, aq);
707
+ const aqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
708
+ // console.log("normalize3 faq res: ", aqQueryRes)
709
+ const rq = createReturnTypeQuery(typ.typeName);
710
+ fs.writeFileSync(pathToQuery, rq);
711
+ const rqQueryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
712
+ // console.log("normalize3 frq res: ", rqQueryRes)
713
+ const normalFormBuilder = [];
714
+ normalFormBuilder.push("(");
715
+ aqQueryRes.forEach((obj, i) => {
716
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms));
717
+ if (i < aqQueryRes.length - 1) {
718
+ normalFormBuilder.push(", ");
719
+ }
720
+ });
721
+ normalFormBuilder.push(") => ");
722
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, rqQueryRes[0], knownTypes, targetTypes, knownNormalForms));
723
+ const normalForm = normalFormBuilder.join("");
724
+ targetTypes.add(normalForm);
725
+ knownNormalForms.set(typ.typeName, normalForm);
726
+ return normalForm;
727
+ }
728
+ }
729
+ else if ((0, utils_1.isQLInterface)(typ.typeQLClass)) {
730
+ if (knownTypes.has(typ.typeName)) {
731
+ const definition = knownTypes.get(typ.typeName);
732
+ const components = definition.components;
733
+ const normalFormBuilder = [];
734
+ normalFormBuilder.push("{");
735
+ components.forEach((obj, i) => {
736
+ if ((0, utils_1.isQLLabel)(obj.typeQLClass)) {
737
+ normalFormBuilder.push("".concat(" ", obj.typeName, ": "));
738
+ }
739
+ else {
740
+ normalFormBuilder.push("".concat(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms)));
741
+ if (i < components.length - 1) {
742
+ normalFormBuilder.push("; ");
743
+ }
744
+ else {
745
+ normalFormBuilder.push(" ");
746
+ }
747
+ }
748
+ });
749
+ normalFormBuilder.push("}");
750
+ const normalForm = normalFormBuilder.join("");
751
+ targetTypes.add(normalForm);
752
+ knownNormalForms.set(typ.typeName, normalForm);
753
+ return normalForm;
754
+ }
755
+ else {
756
+ const q = createInterfaceComponentsTypeQuery(typ.typeName);
757
+ // console.log("normalize3 iq: ", q)
758
+ fs.writeFileSync(pathToQuery, q);
759
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
760
+ // console.log("normalize3 iq res: ", queryRes)
761
+ const normalFormBuilder = [];
762
+ normalFormBuilder.push("{");
763
+ queryRes.forEach((obj, i) => {
764
+ const key = obj.typeName.split(": ")[0];
765
+ const val = obj.typeName.split(": ")[1];
766
+ normalFormBuilder.push("".concat(" ", key, ": ", normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: val, typeQLClass: obj.typeQLClass }, knownTypes, targetTypes, knownNormalForms)));
767
+ if (i < queryRes.length - 1) {
768
+ normalFormBuilder.push("; ");
769
+ }
770
+ else {
771
+ normalFormBuilder.push(" ");
772
+ }
773
+ });
774
+ normalFormBuilder.push("}");
775
+ const normalForm = normalFormBuilder.join("");
776
+ targetTypes.add(normalForm);
777
+ knownNormalForms.set(typ.typeName, normalForm);
778
+ return normalForm;
779
+ }
780
+ }
781
+ else if ((0, utils_1.isQLTuple)(typ.typeQLClass)) {
782
+ // NOTE: some tuples have identifiers
783
+ if (knownTypes.has(typ.typeName)) {
784
+ const definition = knownTypes.get(typ.typeName);
785
+ const components = definition.components;
786
+ const normalFormBuilder = [];
787
+ normalFormBuilder.push("[");
788
+ components.forEach((obj, i) => {
789
+ if (!(0, utils_1.isQLIdentifier)(obj.typeQLClass)) {
790
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms));
791
+ if (i < components.length - 1) {
792
+ normalFormBuilder.push(", ");
793
+ }
794
+ }
795
+ });
796
+ normalFormBuilder.push("]");
797
+ const normalForm = normalFormBuilder.join("");
798
+ targetTypes.add(normalForm);
799
+ knownNormalForms.set(typ.typeName, normalForm);
800
+ return normalForm;
801
+ }
802
+ else {
803
+ const q = createTupleComponentsTypeQuery(typ.typeName);
804
+ // console.log("normalize3 tq: ", q)
805
+ fs.writeFileSync(pathToQuery, q);
806
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
807
+ // console.log("normalize3 tq res: ", queryRes)
808
+ const normalFormBuilder = [];
809
+ normalFormBuilder.push("[");
810
+ queryRes.forEach((obj, i) => {
811
+ if (!(0, utils_1.isQLIdentifier)(obj.typeQLClass)) {
812
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms));
813
+ if (i < queryRes.length - 1) {
814
+ normalFormBuilder.push(", ");
815
+ }
816
+ }
817
+ });
818
+ normalFormBuilder.push("]");
819
+ const normalForm = normalFormBuilder.join("");
820
+ targetTypes.add(normalForm);
821
+ knownNormalForms.set(typ.typeName, normalForm);
822
+ return normalForm;
823
+ }
824
+ }
825
+ else if ((0, utils_1.isQLUnion)(typ.typeQLClass)) {
826
+ if (knownTypes.has(typ.typeName)) {
827
+ const definition = knownTypes.get(typ.typeName);
828
+ const components = definition.components;
829
+ const normalFormBuilder = [];
830
+ components.forEach((obj, i) => {
831
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms));
832
+ if (i < components.length - 1) {
833
+ normalFormBuilder.push(" | ");
834
+ }
835
+ });
836
+ const normalForm = normalFormBuilder.join("");
837
+ targetTypes.add(normalForm);
838
+ knownNormalForms.set(typ.typeName, normalForm);
839
+ return normalForm;
840
+ }
841
+ else {
842
+ const q = createUnionComponentsTypeQuery(typ.typeName);
843
+ // console.log("normalize3 uq: ", q)
844
+ fs.writeFileSync(pathToQuery, q);
845
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
846
+ // console.log("normalize3 uq res: ", queryRes)
847
+ const normalFormBuilder = [];
848
+ queryRes.forEach((obj, i) => {
849
+ normalFormBuilder.push(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, obj, knownTypes, targetTypes, knownNormalForms));
850
+ if (i < queryRes.length - 1) {
851
+ normalFormBuilder.push(" | ");
852
+ }
853
+ });
854
+ const normalForm = normalFormBuilder.join("");
855
+ targetTypes.add(normalForm);
856
+ knownNormalForms.set(typ.typeName, normalForm);
857
+ return normalForm;
858
+ }
859
+ }
860
+ else if ((0, utils_1.isQLArray)(typ.typeQLClass)) {
861
+ if (knownTypes.has(typ.typeName)) {
862
+ const definition = knownTypes.get(typ.typeName);
863
+ const components = definition.components;
864
+ const elementType = components[0];
865
+ const normalForm = "".concat(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, elementType, knownTypes, targetTypes, knownNormalForms), "[]");
866
+ targetTypes.add(normalForm);
867
+ knownNormalForms.set(typ.typeName, normalForm);
868
+ return normalForm;
869
+ }
870
+ else if (knownTypes.has(typ.typeName.replace("[]", ""))) {
871
+ const definition = knownTypes.get(typ.typeName.replace("[]", ""));
872
+ const normalForm = "".concat(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, definition, knownTypes, targetTypes, knownNormalForms), "[]");
873
+ targetTypes.add(normalForm);
874
+ knownNormalForms.set(typ.typeName, normalForm);
875
+ return normalForm;
876
+ }
877
+ else {
878
+ const q = createArrayTypeQuery(typ.typeName);
879
+ // console.log("normalize3 aq: ", q)
880
+ fs.writeFileSync(pathToQuery, q);
881
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
882
+ // console.log("normalize3 aq res: ", queryRes)
883
+ const normalForm = "".concat(normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], knownTypes, targetTypes, knownNormalForms), "[]");
884
+ targetTypes.add(normalForm);
885
+ knownNormalForms.set(typ.typeName, normalForm);
886
+ return normalForm;
887
+ }
888
+ }
889
+ else if ((0, utils_1.isQLLocalTypeAccess)(typ.typeQLClass)) {
890
+ if (knownTypes.has(typ.typeName)) {
891
+ const definition = knownTypes.get(typ.typeName);
892
+ const normalForm = normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, { typeName: definition.typeName, typeQLClass: definition.typeQLClass }, knownTypes, targetTypes, knownNormalForms);
893
+ targetTypes.add(normalForm);
894
+ knownNormalForms.set(typ.typeName, normalForm);
895
+ return normalForm;
896
+ }
897
+ else {
898
+ const q = createLocalTypeAccessTypeQuery(typ.typeName);
899
+ // console.log("normalize3 ltaq: ", q)
900
+ fs.writeFileSync(pathToQuery, q);
901
+ const queryRes = extractTypes(pathToCodeQL, pathToQuery, pathToDatabase, outDir);
902
+ // console.log("normalize3 ltaq res: ", queryRes)
903
+ const normalForm = normalize3(pathToCodeQL, pathToQuery, pathToDatabase, outDir, queryRes[0], knownTypes, targetTypes, knownNormalForms);
904
+ targetTypes.add(normalForm);
905
+ knownNormalForms.set(typ.typeName, normalForm);
906
+ return normalForm;
907
+ }
908
+ }
909
+ else {
910
+ console.log(`normalize3: this doesn't exist: ${JSON.stringify(typ)}`);
911
+ console.error(`normalize3: this doesn't exist: ${JSON.stringify(typ)}`);
912
+ throw Error(`normalize3: this doesn't exist: ${JSON.stringify(typ)}`);
913
+ }
914
+ };
915
+ const getRelevantHeaders4 = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, headers, holeType, relevantTypes, knownTypeLocations) => {
916
+ // TODO:
917
+ // take a type and the header it belongs to.
918
+ // check if that type is directly in relevant types. If so, the header with that type is relevant.
919
+ // if not, then try running a consistency check with all the relevant types.
920
+ // if there's a consistent type, then the header with that type is relevant.
921
+ // if not, then we need to split that type.
922
+ // if it's an arrow type, recurse on the return type.
923
+ // if it's a tuple type, recurse on the components.
924
+ const relevantHeaders = new Set();
925
+ const targetTypes = getTargetTypes(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, holeType);
926
+ headers.forEach(header => {
927
+ if (isRelevantHeader(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, header, targetTypes, relevantTypes, knownTypeLocations)) {
928
+ // TODO: need to strip identifiers from functions, interfaces, tuples, ...
929
+ relevantHeaders.add(header.constDeclaration);
930
+ }
931
+ });
932
+ return relevantHeaders;
933
+ };
934
+ exports.getRelevantHeaders4 = getRelevantHeaders4;
935
+ const getTargetTypes = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, holeType) => {
936
+ const targetTypes = new Map();
937
+ targetTypes.set(holeType.typeName, holeType);
938
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, holeType, targetTypes);
939
+ return targetTypes;
940
+ };
941
+ const getTargetTypesHelper = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, currType, targetTypes) => {
942
+ // console.log("===Helper===")
943
+ // console.log("currType: ", currType)
944
+ // console.log("targetTypes: ", targetTypes)
945
+ if ((0, utils_1.isQLFunction)(currType.typeQLClass)) {
946
+ if (relevantTypes.has(currType.typeName)) {
947
+ const definition = relevantTypes.get(currType.typeName);
948
+ const components = definition.components;
949
+ const returnType = components[0];
950
+ targetTypes.set(returnType.typeName, returnType);
951
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, returnType, targetTypes);
952
+ }
953
+ else {
954
+ const q = createReturnTypeQuery(currType.typeName);
955
+ const qPath = path.join(pathToQueryDir, "types.ql");
956
+ fs.writeFileSync(qPath, q);
957
+ const queryRes = extractTypes(pathToCodeQL, qPath, pathToDatabase, outDir);
958
+ // console.log("fqr: ", queryRes)
959
+ const returnType = queryRes[0];
960
+ targetTypes.set(returnType.typeName, returnType);
961
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, returnType, targetTypes);
962
+ }
963
+ }
964
+ else if ((0, utils_1.isQLTuple)(currType.typeQLClass)) {
965
+ if (relevantTypes.has(currType.typeName)) {
966
+ const definition = relevantTypes.get(currType.typeName);
967
+ const components = definition.components;
968
+ for (const comp of components) {
969
+ targetTypes.set(comp.typeName, comp);
970
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, comp, targetTypes);
971
+ }
972
+ }
973
+ else {
974
+ const q = createTupleComponentsTypeQuery(currType.typeName);
975
+ const qPath = path.join(pathToQueryDir, "types.ql");
976
+ fs.writeFileSync(qPath, q);
977
+ const queryRes = extractTypes(pathToCodeQL, qPath, pathToDatabase, outDir);
978
+ // console.log("tqr: ", queryRes)
979
+ for (const comp of queryRes) {
980
+ targetTypes.set(comp.typeName, comp);
981
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, comp, targetTypes);
982
+ }
983
+ }
984
+ }
985
+ else if ((0, utils_1.isQLLocalTypeAccess)(currType.typeQLClass)) {
986
+ if (relevantTypes.has(currType.typeName)) {
987
+ const definition = relevantTypes.get(currType.typeName);
988
+ const nextType = { typeName: definition.typeName, typeQLClass: definition.typeQLClass };
989
+ getTargetTypesHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, relevantTypes, nextType, targetTypes);
990
+ }
991
+ }
992
+ };
993
+ const isRelevantHeader = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, header, targetTypes, relevantTypes, knownTypeLocations) => {
994
+ // console.log("===isRelevantHeader===")
995
+ const currType = { typeName: header.typeAnnotation, typeQLClass: header.typeQLClass };
996
+ return isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, currType, targetTypes, relevantTypes, knownTypeLocations);
997
+ // console.log("currType: ", currType)
998
+ // if (isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, currType, relevantTypes, knownTypeLocations)) {
999
+ // return true;
1000
+ // } else {
1001
+ // if (isQLFunction(header.typeQLClass)) {
1002
+ // // console.log("isQLFunction")
1003
+ // // if function, recurse on return type
1004
+ // const returnType: typesObject = header.components[0];
1005
+ // return isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, returnType, relevantTypes, knownTypeLocations);
1006
+ //
1007
+ // } else if (isQLTuple(header.typeQLClass)) {
1008
+ // // console.log("isQLTuple")
1009
+ // // if tuple, recurse on component types
1010
+ // const components = header.components;
1011
+ // for (const comp of components) {
1012
+ // if (isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, comp, relevantTypes, knownTypeLocations)) return true;
1013
+ // }
1014
+ // }
1015
+ // return false;
1016
+ // };
1017
+ };
1018
+ const isRelevantHeaderHelper = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, typ, targetTypes, relevantTypes, knownTypeLocations) => {
1019
+ if (targetTypes.has(typ.typeName)) {
1020
+ return true;
1021
+ }
1022
+ // this can be a big file that compiles once.
1023
+ const scrutineeType = typ.typeName;
1024
+ const comparisonTypes = Array.from(targetTypes.keys());
1025
+ if (isConsistent(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, scrutineeType, comparisonTypes, knownTypeLocations)) {
1026
+ return true;
1027
+ }
1028
+ else if ((0, utils_1.isQLFunction)(typ.typeQLClass)) {
1029
+ // if (isQLFunction(typ.typeQLClass)) {
1030
+ if (relevantTypes.has(typ.typeName)) {
1031
+ const definition = relevantTypes.get(typ.typeName);
1032
+ const components = definition.components;
1033
+ const returnType = components[0];
1034
+ return isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, returnType, targetTypes, relevantTypes, knownTypeLocations);
1035
+ }
1036
+ else {
1037
+ console.log("fquery");
1038
+ const q = createReturnTypeQuery(typ.typeName);
1039
+ const qPath = path.join(pathToQueryDir, "types.ql");
1040
+ fs.writeFileSync(qPath, q);
1041
+ const queryRes = extractTypes(pathToCodeQL, qPath, pathToDatabase, outDir);
1042
+ return isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, queryRes[0], targetTypes, relevantTypes, knownTypeLocations);
1043
+ }
1044
+ }
1045
+ else if ((0, utils_1.isQLTuple)(typ.typeQLClass)) {
1046
+ if (relevantTypes.has(typ.typeName)) {
1047
+ const definition = relevantTypes.get(typ.typeName);
1048
+ const components = definition.components;
1049
+ for (const comp of components) {
1050
+ if (isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, comp, targetTypes, relevantTypes, knownTypeLocations))
1051
+ return true;
1052
+ }
1053
+ }
1054
+ else {
1055
+ console.log("tquery");
1056
+ const q = createTupleComponentsTypeQuery(typ.typeName);
1057
+ const qPath = path.join(pathToQueryDir, "types.ql");
1058
+ fs.writeFileSync(qPath, q);
1059
+ const queryRes = extractTypes(pathToCodeQL, qPath, pathToDatabase, outDir);
1060
+ for (const comp of queryRes) {
1061
+ if (isRelevantHeaderHelper(pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, comp, targetTypes, relevantTypes, knownTypeLocations))
1062
+ return true;
1063
+ }
1064
+ }
1065
+ }
1066
+ return false;
1067
+ };
1068
+ // checks if two types are consistent
1069
+ // take in two types and write a consistency checker function to a file
1070
+ // run the typescript compiler on it to invoke static errors
1071
+ // if there are no errors, then the two types are consistent
1072
+ const isConsistent = (pathToCodeQL, pathtoQueryDir, pathToDatabase, outDir, scrutineeType, comparisonTypes, knownTypeLocations) => {
1073
+ // TODO: this is still too slow. let's just import everything and compile everything
1074
+ // TODO: abstract this
1075
+ const builder = [];
1076
+ for (const [file, dependencies] of knownTypeLocations.locationToType.entries()) {
1077
+ builder.push(`import {${dependencies.join(", ")}} from "${file}"`);
1078
+ }
1079
+ for (const comp of comparisonTypes) {
1080
+ builder.push(`function check(a: ${scrutineeType}): ${comp} { return a; }`);
1081
+ }
1082
+ const checkFunction = builder.join("\n");
1083
+ const checkPath = path.join(outDir, "checkConsistency.ts");
1084
+ fs.writeFileSync(checkPath, checkFunction);
1085
+ const numChecks = comparisonTypes.length;
1086
+ try {
1087
+ (0, child_process_1.execSync)(`tsc ${checkPath}`);
1088
+ }
1089
+ catch (err) {
1090
+ const numErrors = err.stdout.toString().split("\n").length;
1091
+ return numErrors < numChecks;
1092
+ }
1093
+ return false;
1094
+ /*
1095
+ // extract necessary dependencies by invoking static dependency error
1096
+ const dependencyErrorInvoker = createDependencyErrorInvoker([scrutineeType, ...comparisonTypes]);
1097
+ const invokerPath = path.join(outDir, "invokeDependencyError.ts");
1098
+ fs.writeFileSync(invokerPath, dependencyErrorInvoker);
1099
+
1100
+ const dependencies: string[] = [];
1101
+
1102
+ try {
1103
+ execSync(`tsc ${invokerPath}`);
1104
+ } catch (err: any) {
1105
+ dependencies.push(...extractDependencies(err.stdout.toString()));
1106
+ }
1107
+
1108
+ // TODO: this is slow. we should just use a global map to find the locations.
1109
+ // use CodeQL to find their locations
1110
+ // we could do this for each comparisonType, but lots of individual queries are expensive.
1111
+ // const filesAndDependencies = resolveDependencies(pathToCodeQL, pathtoQueryDir, pathToDatabase, outDir, dependencies);
1112
+
1113
+ // loop over dependencies. for each dep, check in knownTypes.typeToLocation to see the location.
1114
+ // const filesAndDependencies = dependencies.reduce((m, dep) => {
1115
+ // const location = knownTypeLocations.typeToLocation.get(dep);
1116
+ // if (location) {
1117
+ // if (!m.has(location)) {
1118
+ // m.set(location, [dep]);
1119
+ // } else {
1120
+ // const pair = m.get(location)!;
1121
+ // pair.push(dep);
1122
+ // m.set(location, pair);
1123
+ // }
1124
+ // }
1125
+ // return m;
1126
+ // }, new Map<string, string[]>);
1127
+ const filesAndDependencies = resolveDependencies(pathToCodeQL, pathtoQueryDir, pathToDatabase, outDir, dependencies, knownTypeLocations);
1128
+ console.log("filesAndDependencies: ", filesAndDependencies)
1129
+
1130
+ // inject those dependencies into the checker
1131
+ for (const comparisonType of comparisonTypes) {
1132
+ const checkFunction = createConsistencyCheckFunction(scrutineeType, comparisonType, filesAndDependencies);
1133
+ const checkPath = path.join(outDir, "checkConsistency.ts");
1134
+ fs.writeFileSync(checkPath, checkFunction);
1135
+
1136
+ try {
1137
+ execSync(`tsc ${checkPath}`);
1138
+ return true;
1139
+ } catch (err: any) {
1140
+ console.log(`types are not consistent: ${err}`);
1141
+ }
1142
+ }
1143
+ return false;
1144
+ */
1145
+ };
1146
+ // tsc will print an error "Cannot find name <name>" if it encounters a dependency error.
1147
+ // extract the dependency from that message.
1148
+ const extractDependencies = (errorMsg) => {
1149
+ // TODO: this should be done once at the beginning to establish a global import map
1150
+ const dependencies = [];
1151
+ const lines = errorMsg.split("\n");
1152
+ lines.forEach(line => {
1153
+ const matches = line.match(/(.*Cannot find name \')(.*)(\'.)/);
1154
+ if (matches) {
1155
+ dependencies.push(matches[2]);
1156
+ }
1157
+ });
1158
+ return dependencies;
1159
+ };
1160
+ // run a query to get the dependencies and their file locations.
1161
+ const resolveDependencies = (pathToCodeQL, pathToQueryDir, pathToDatabase, outDir, dependencies, knownTypeLocations) => {
1162
+ return dependencies.reduce((m, dep) => {
1163
+ const location = knownTypeLocations.typeToLocation.get(dep);
1164
+ if (location) {
1165
+ if (!m.has(location)) {
1166
+ m.set(location, [dep]);
1167
+ }
1168
+ else {
1169
+ const pair = m.get(location);
1170
+ pair.push(dep);
1171
+ m.set(location, pair);
1172
+ }
1173
+ }
1174
+ return m;
1175
+ }, new Map);
1176
+ // const q = createImportQuery(dependencies);
1177
+ // fs.writeFileSync(path.join(pathToQueryDir, "imports.ql"), q);
1178
+ //
1179
+ // return extractTypesAndLocations(pathToCodeQL, path.join(pathToQueryDir, "imports.ql"), pathToDatabase, outDir);
1180
+ };
1181
+ const createDependencyErrorInvoker = (possibleDependencies) => {
1182
+ const builder = [];
1183
+ for (const pdep of possibleDependencies) {
1184
+ builder.push(`let x: ${pdep};`);
1185
+ }
1186
+ return builder.join("\n");
1187
+ };
1188
+ const createConsistencyCheckFunction = (scrutineeType, comparisonType, filesAndDependencies) => {
1189
+ const builder = [];
1190
+ for (const [file, dependencies] of filesAndDependencies.entries()) {
1191
+ builder.push(`import {${dependencies.join(", ")}} from "${file}"`);
1192
+ }
1193
+ builder.push(`function check(a: ${scrutineeType}): ${comparisonType} { return a; }`);
1194
+ return builder.join("\n");
1195
+ };
1196
+ const createImportQuery = (dependencies) => {
1197
+ const dependencyDisjunction = dependencies.reduce((acc, curr, i) => {
1198
+ if (i < dependencies.length - 1) {
1199
+ return acc + `t.getIdentifier().toString() = "${curr}" or `;
1200
+ }
1201
+ return acc + `t.getIdentifier().toString() = "${curr}"`;
1202
+ }, "");
1203
+ return [
1204
+ "/**",
1205
+ " * @id imports",
1206
+ " * @name Imports",
1207
+ " * @description Resolve dependencies during consistency check.",
1208
+ " */",
1209
+ "",
1210
+ "import javascript",
1211
+ "",
1212
+ "from File f, TypeAliasDeclaration t",
1213
+ `where(${dependencyDisjunction}) and t.getFile() = f`,
1214
+ "select t.getIdentifier().toString(), f.toString()"
1215
+ ].join("\n");
1216
+ };
1217
+ const createHoleTypeQuery = () => {
1218
+ return [
1219
+ "/**",
1220
+ " * @id types",
1221
+ " * @name Types",
1222
+ " * @description Find the specified type.",
1223
+ " */",
1224
+ "",
1225
+ "import javascript",
1226
+ "",
1227
+ "from VariableDeclarator d",
1228
+ `where d.getAChild().toString() = "_()"`,
1229
+ "select d.getTypeAnnotation().toString(), d.getTypeAnnotation().getAPrimaryQlClass()"
1230
+ ].join("\n");
1231
+ };
1232
+ const createArgTypeQuery = (typeToQuery) => {
1233
+ return [
1234
+ "/**",
1235
+ " * @id types",
1236
+ " * @name Types",
1237
+ " * @description Find the specified type.",
1238
+ " */",
1239
+ "",
1240
+ "import javascript",
1241
+ "",
1242
+ "from FunctionTypeExpr t, TypeExpr e",
1243
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and e = t.getAParameter().getTypeAnnotation()`,
1244
+ "select e.toString(), e.getAPrimaryQlClass()"
1245
+ ].join("\n");
1246
+ };
1247
+ const createReturnTypeQuery = (typeToQuery) => {
1248
+ return [
1249
+ "/**",
1250
+ " * @id types",
1251
+ " * @name Types",
1252
+ " * @description Find the specified type.",
1253
+ " */",
1254
+ "",
1255
+ "import javascript",
1256
+ "",
1257
+ "from FunctionTypeExpr t, TypeExpr e",
1258
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and e = t.getReturnTypeAnnotation()`,
1259
+ "select e.toString(), e.getAPrimaryQlClass()"
1260
+ ].join("\n");
1261
+ };
1262
+ const createInterfaceComponentsTypeQuery = (typeToQuery) => {
1263
+ return [
1264
+ "/**",
1265
+ " * @id types",
1266
+ " * @name Types",
1267
+ " * @description Find the specified type.",
1268
+ " */",
1269
+ "",
1270
+ "import javascript",
1271
+ "",
1272
+ "from InterfaceTypeExpr t, FieldDeclaration e, int i",
1273
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and i = [0..t.getNumChild()] and e = t.getChild(i)`,
1274
+ // "select e.toString(), e.getName(), e.getTypeAnnotation(), e.getTypeAnnotation().getAPrimaryQlClass(), i",
1275
+ `select concat(string a, string b | a = e.getName() and b = e.getTypeAnnotation().toString() | a + ": " + b), e.getTypeAnnotation().getAPrimaryQlClass(), i`,
1276
+ "order by i"
1277
+ ].join("\n");
1278
+ };
1279
+ const createTupleComponentsTypeQuery = (typeToQuery) => {
1280
+ return [
1281
+ "/**",
1282
+ " * @id types",
1283
+ " * @name Types",
1284
+ " * @description Find the specified type.",
1285
+ " */",
1286
+ "",
1287
+ "import javascript",
1288
+ "",
1289
+ "from TupleTypeExpr t, TypeExpr e, int i",
1290
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and i = [0..t.getNumElementType()] and e = t.getElementType(i)`,
1291
+ "select e.toString(), e.getAPrimaryQlClass(), i",
1292
+ "order by i"
1293
+ ].join("\n");
1294
+ };
1295
+ const createUnionComponentsTypeQuery = (typeToQuery) => {
1296
+ return [
1297
+ "/**",
1298
+ " * @id types",
1299
+ " * @name Types",
1300
+ " * @description Find the specified type.",
1301
+ " */",
1302
+ "",
1303
+ "import javascript",
1304
+ "",
1305
+ "from UnionTypeExpr t, TypeExpr e, int i",
1306
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and i = [0..t.getNumElementType()] and e = t.getElementType(i)`,
1307
+ "select e.toString(), e.getAPrimaryQlClass(), i",
1308
+ "order by i"
1309
+ ].join("\n");
1310
+ };
1311
+ const createArrayTypeQuery = (typeToQuery) => {
1312
+ return [
1313
+ "/**",
1314
+ " * @id types",
1315
+ " * @name Types",
1316
+ " * @description Find the specified type.",
1317
+ " */",
1318
+ "",
1319
+ "import javascript",
1320
+ "",
1321
+ "from ArrayTypeExpr t, TypeExpr e",
1322
+ `where t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and e = t.getElementType()`,
1323
+ "select e.toString(), e.getAPrimaryQlClass()"
1324
+ ].join("\n");
1325
+ };
1326
+ const createLocalTypeAccessTypeQuery = (typeToQuery) => {
1327
+ return [
1328
+ "/**",
1329
+ " * @id types",
1330
+ " * @name Types",
1331
+ " * @description Find the specified type.",
1332
+ " */",
1333
+ "",
1334
+ "import javascript",
1335
+ "",
1336
+ "from LocalTypeAccess t, TypeExpr e, TypeAliasDeclaration td",
1337
+ `where(t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and e = t.getLocalTypeName().getADeclaration().getEnclosingStmt().(TypeAliasDeclaration).getDefinition()) or`,
1338
+ `(t.toString() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and td.getName() = "${(0, utils_1.escapeQuotes)(typeToQuery)}" and td.getFile().toString() = t.getLocalTypeName().getADeclaration().getEnclosingStmt().(Import).resolveImportedPath().getPath() and e = td.getDefinition())`,
1339
+ "select e.toString(), e.getAPrimaryQlClass()"
1340
+ ].join("\n");
1341
+ };