@jpoly1219/context-extractor 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ };