@profile-psl/psl-parser 0.1.0

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/utilities.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { FinderPaths } from "./config";
2
+ import { Member, Method, ParsedDocument } from "./parser";
3
+ import { Position, Token } from "./tokenizer";
4
+ export interface FinderResult {
5
+ fsPath: string;
6
+ member?: Member;
7
+ }
8
+ export declare const dummyPosition: Position;
9
+ export declare class ParsedDocFinder {
10
+ parsedDocument: ParsedDocument;
11
+ paths: FinderPaths;
12
+ procName: string;
13
+ private hierarchy;
14
+ constructor(parsedDocument: ParsedDocument, paths: FinderPaths, getWorkspaceDocumentText?: (fsPath: string) => Promise<string>);
15
+ resolveResult(callTokens: Token[]): Promise<FinderResult>;
16
+ newFinder(routineName: string): Promise<ParsedDocFinder>;
17
+ /**
18
+ * Search the parsed document and parents for a particular member
19
+ */
20
+ searchParser(queriedToken: Token): Promise<FinderResult>;
21
+ searchInDocument(queriedId: string): Promise<FinderResult>;
22
+ findAllInDocument(results?: FinderResult[]): Promise<FinderResult[]>;
23
+ resolveFileDefinitionDirectory(tableName: string): Promise<string>;
24
+ private searchForParent;
25
+ private searchInMethod;
26
+ private findActiveMethod;
27
+ private getWorkspaceDocumentText;
28
+ }
29
+ /**
30
+ * Get the tokens on the line of position, as well as the specific index of the token at position
31
+ */
32
+ export declare function searchTokens(tokens: Token[], position: Position): {
33
+ tokensOnLine: Token[];
34
+ index: number;
35
+ };
36
+ export declare function getCallTokens(tokensOnLine: Token[], index: number): Token[];
37
+ export declare function resolve(tokens: Token[]): number;
38
+ export declare function findCallable(tokensOnLine: Token[], index: number): {
39
+ callTokens: Token[];
40
+ parameterIndex: number;
41
+ };
42
+ export declare function getLineAfter(method: Method): number;
43
+ export declare function getCommentsOnLine(parsedDocument: ParsedDocument, lineNumber: number): Token[];
package/utilities.js ADDED
@@ -0,0 +1,427 @@
1
+ import * as fs from "fs";
2
+ import * as fsx from "fs-extra";
3
+ import * as jsonc from "jsonc-parser";
4
+ import * as path from "path";
5
+ import { MemberClass, parseText } from "./parser";
6
+ import { Position, Token } from "./tokenizer";
7
+ export const dummyPosition = new Position(0, 0);
8
+ export class ParsedDocFinder {
9
+ parsedDocument;
10
+ paths;
11
+ procName;
12
+ hierarchy = [];
13
+ constructor(parsedDocument, paths, getWorkspaceDocumentText) {
14
+ this.parsedDocument = parsedDocument;
15
+ this.paths = paths;
16
+ if (getWorkspaceDocumentText)
17
+ this.getWorkspaceDocumentText = getWorkspaceDocumentText;
18
+ this.procName = path.basename(this.paths.activeRoutine).split(".")[0];
19
+ }
20
+ async resolveResult(callTokens) {
21
+ // TODO: (Mischa Reitsma) Reset the finder a few times. Most of them can be a local const finder = this.newFinder(), but not all. Not going to change it now
22
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
23
+ let finder = this;
24
+ if (callTokens.length === 1) {
25
+ const result = await finder.searchParser(callTokens[0]);
26
+ // check for core class or tables
27
+ if (!result) {
28
+ const pslClsNames = await getPslClsNames(this.paths.corePsl);
29
+ if (pslClsNames.indexOf(callTokens[0].value) >= 0) {
30
+ const finder = await this.newFinder(callTokens[0].value);
31
+ return {
32
+ fsPath: finder.paths.activeRoutine,
33
+ };
34
+ }
35
+ const tableName = callTokens[0].value.replace("Record", "");
36
+ const fileDefinitionDirectory = await this.resolveFileDefinitionDirectory(tableName);
37
+ if (fileDefinitionDirectory) {
38
+ return {
39
+ fsPath: path.join(fileDefinitionDirectory, tableName.toUpperCase() + ".TBL"),
40
+ };
41
+ }
42
+ else if (callTokens[0] === this.parsedDocument.extending) {
43
+ finder = await finder.newFinder(callTokens[0].value);
44
+ return {
45
+ fsPath: finder.paths.activeRoutine,
46
+ };
47
+ }
48
+ else if (callTokens[0].value === "this" ||
49
+ callTokens[0].value === this.procName) {
50
+ return {
51
+ fsPath: this.paths.activeRoutine,
52
+ };
53
+ }
54
+ }
55
+ // handle static types
56
+ else if (result.member.types[0] === callTokens[0]) {
57
+ finder = await finder.newFinder(result.member.id.value);
58
+ return {
59
+ fsPath: finder.paths.activeRoutine,
60
+ };
61
+ }
62
+ return result;
63
+ }
64
+ else {
65
+ let result;
66
+ for (let index = 0; index < callTokens.length; index++) {
67
+ const token = callTokens[index];
68
+ if (index === 0) {
69
+ // handle core class
70
+ const pslClsNames = await getPslClsNames(this.paths.corePsl);
71
+ if (pslClsNames.indexOf(token.value) >= 0) {
72
+ finder = await finder.newFinder(token.value);
73
+ continue;
74
+ }
75
+ // skip over "this"
76
+ else if (token.value === "this" ||
77
+ token.value === this.procName) {
78
+ result = {
79
+ fsPath: this.paths.activeRoutine,
80
+ };
81
+ continue;
82
+ }
83
+ else {
84
+ result = await finder.searchParser(token);
85
+ }
86
+ }
87
+ if (!result || (result.fsPath === this.paths.activeRoutine
88
+ && !result.member)) {
89
+ result = await finder.searchInDocument(token.value);
90
+ }
91
+ if (!result)
92
+ return null;
93
+ if (!callTokens[index + 1])
94
+ return result;
95
+ let type = result.member.types[0].value;
96
+ if (type === "void")
97
+ type = "Primitive"; // TODO whack hack
98
+ finder = await finder.newFinder(type);
99
+ result = undefined;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+ async newFinder(routineName) {
105
+ if (routineName.startsWith("Record") && routineName !== "Record") {
106
+ const tableName = routineName.replace("Record", "");
107
+ const tableDirectory = await this.resolveFileDefinitionDirectory(tableName.toLowerCase());
108
+ if (!tableDirectory)
109
+ return null;
110
+ const columns = (await fsx.readdir(tableDirectory))
111
+ .filter(file => file.endsWith(".COL"))
112
+ .map(col => {
113
+ const colName = col
114
+ .replace(`${tableName}-`, "")
115
+ .replace(".COL", "")
116
+ .toLowerCase();
117
+ const ret = {
118
+ id: new Token(1 /* Type.Alphanumeric */, colName, dummyPosition),
119
+ memberClass: MemberClass.column,
120
+ modifiers: [],
121
+ types: [new Token(1 /* Type.Alphanumeric */, "String", dummyPosition)],
122
+ };
123
+ return ret;
124
+ });
125
+ const text = await this.getWorkspaceDocumentText(path.join(tableDirectory, `${tableName.toUpperCase()}.TBL`));
126
+ const parsed = jsonc.parse(text);
127
+ const parentFileId = parsed.PARFID;
128
+ const extendingValue = parentFileId ? `Record${parentFileId}` : "Record";
129
+ const parsedDocument = {
130
+ comments: [],
131
+ declarations: [],
132
+ extending: new Token(1 /* Type.Alphanumeric */, extendingValue, dummyPosition),
133
+ methods: [],
134
+ properties: columns,
135
+ pslPackage: "",
136
+ tokens: [],
137
+ };
138
+ const newPaths = Object.create(this.paths);
139
+ newPaths.activeRoutine = "";
140
+ newPaths.activeTable = tableDirectory;
141
+ return new ParsedDocFinder(parsedDocument, newPaths, this.getWorkspaceDocumentText);
142
+ }
143
+ const pathsWithoutExtensions = this.paths.projectPsl
144
+ .map(pslPath => path.join(pslPath, routineName));
145
+ for (const pathWithoutExtension of pathsWithoutExtensions) {
146
+ for (const extension of [".PROC", ".psl", ".PSL"]) {
147
+ const possiblePath = pathWithoutExtension + extension;
148
+ const routineText = await this.getWorkspaceDocumentText(possiblePath);
149
+ if (!routineText)
150
+ continue;
151
+ const newPaths = Object.create(this.paths);
152
+ newPaths.activeRoutine = possiblePath;
153
+ return new ParsedDocFinder(parseText(routineText), newPaths, this.getWorkspaceDocumentText);
154
+ }
155
+ }
156
+ return null;
157
+ }
158
+ /**
159
+ * Search the parsed document and parents for a particular member
160
+ */
161
+ async searchParser(queriedToken) {
162
+ const activeMethod = this.findActiveMethod(queriedToken);
163
+ if (activeMethod) {
164
+ const variable = this.searchInMethod(activeMethod, queriedToken);
165
+ if (variable)
166
+ return { member: variable, fsPath: this.paths.activeRoutine };
167
+ }
168
+ return this.searchInDocument(queriedToken.value);
169
+ }
170
+ async searchInDocument(queriedId) {
171
+ let foundProperty;
172
+ if (this.paths.activeTable) {
173
+ foundProperty = this.parsedDocument.properties
174
+ .find(p => p.id.value.toLowerCase() === queriedId.toLowerCase());
175
+ if (foundProperty) {
176
+ const tableName = path.basename(this.paths.activeTable)
177
+ .toUpperCase();
178
+ return {
179
+ fsPath: path.join(this.paths.activeTable, `${tableName}-` +
180
+ foundProperty.id.value.toUpperCase() +
181
+ ".COL"),
182
+ member: foundProperty,
183
+ };
184
+ }
185
+ }
186
+ foundProperty = this.parsedDocument.properties.find(p => p.id.value === queriedId);
187
+ if (foundProperty)
188
+ return { member: foundProperty, fsPath: this.paths.activeRoutine };
189
+ const foundMethod = this.parsedDocument.methods.find(p => p.id.value === queriedId);
190
+ if (foundMethod)
191
+ return { member: foundMethod, fsPath: this.paths.activeRoutine };
192
+ if (this.parsedDocument.extending) {
193
+ const parentRoutineName = this.parsedDocument.extending.value;
194
+ if (this.hierarchy.indexOf(parentRoutineName) > -1)
195
+ return null;
196
+ const parentFinder = await this.searchForParent(parentRoutineName);
197
+ if (!parentFinder)
198
+ return null;
199
+ return parentFinder.searchInDocument(queriedId);
200
+ }
201
+ return null;
202
+ }
203
+ async findAllInDocument(results) {
204
+ if (!results)
205
+ results = [];
206
+ const addToResults = (result) => {
207
+ if (!results.find(r => r.member.id.value === result.member.id.value)) {
208
+ results.push(result);
209
+ }
210
+ };
211
+ if (this.paths.activeTable) {
212
+ this.parsedDocument.properties.forEach(property => {
213
+ const tableName = path.basename(this.paths.activeTable)
214
+ .toUpperCase();
215
+ addToResults({
216
+ member: property,
217
+ fsPath: path.join(this.paths.activeTable, `${tableName}-` +
218
+ property.id.value.toUpperCase() +
219
+ ".COL")
220
+ });
221
+ });
222
+ }
223
+ this.parsedDocument.properties.forEach(property => {
224
+ addToResults({ member: property, fsPath: this.paths.activeRoutine });
225
+ });
226
+ this.parsedDocument.methods.forEach(method => {
227
+ addToResults({ member: method, fsPath: this.paths.activeRoutine });
228
+ });
229
+ if (this.parsedDocument.extending) {
230
+ const parentRoutineName = this.parsedDocument.extending.value;
231
+ if (this.hierarchy.indexOf(parentRoutineName) > -1)
232
+ return results;
233
+ const parentFinder = await this.searchForParent(parentRoutineName);
234
+ if (!parentFinder)
235
+ return results;
236
+ return parentFinder.findAllInDocument(results);
237
+ }
238
+ return results;
239
+ }
240
+ async resolveFileDefinitionDirectory(tableName) {
241
+ for (const tableSource of this.paths.tables) {
242
+ const directory = path.join(tableSource, tableName.toLowerCase());
243
+ if (await fsx.pathExists(directory)) {
244
+ return directory;
245
+ }
246
+ }
247
+ return "";
248
+ }
249
+ async searchForParent(parentRoutineName) {
250
+ const parentFinder = await this.newFinder(parentRoutineName);
251
+ if (!parentFinder)
252
+ return null;
253
+ parentFinder.hierarchy = this.hierarchy.concat(this.paths.activeRoutine);
254
+ return parentFinder;
255
+ }
256
+ searchInMethod(activeMethod, queriedToken) {
257
+ for (const variable of activeMethod.declarations.reverse()) {
258
+ if (queriedToken.position.line < variable.id.position.line)
259
+ continue;
260
+ if (queriedToken.value === variable.id.value)
261
+ return variable;
262
+ }
263
+ for (const parameter of activeMethod.parameters) {
264
+ if (queriedToken.value === parameter.id.value)
265
+ return parameter;
266
+ }
267
+ return null;
268
+ }
269
+ findActiveMethod(queriedToken) {
270
+ const methods = this.parsedDocument.methods
271
+ .filter(method => queriedToken.position.line >= method.id.position.line);
272
+ return methods ? methods.at(-1) : null;
273
+ }
274
+ async getWorkspaceDocumentText(fsPath) {
275
+ return new Promise((resolve) => {
276
+ fs.readFile(fsPath, (err, data) => {
277
+ if (err)
278
+ resolve("");
279
+ resolve(data.toString());
280
+ });
281
+ });
282
+ }
283
+ }
284
+ async function getPslClsNames(dir) {
285
+ try {
286
+ const names = await fsx.readdir(dir);
287
+ return names.map(name => name.split(".")[0]);
288
+ }
289
+ catch {
290
+ return [];
291
+ }
292
+ }
293
+ /**
294
+ * Get the tokens on the line of position, as well as the specific index of the token at position
295
+ */
296
+ export function searchTokens(tokens, position) {
297
+ const tokensOnLine = tokens.filter(t => t.position.line === position.line);
298
+ if (tokensOnLine.length === 0)
299
+ return undefined;
300
+ const index = tokensOnLine.findIndex(t => {
301
+ if (t.isNewLine() || t.isSpace() || t.isTab())
302
+ return null;
303
+ const start = t.position;
304
+ const end = {
305
+ line: t.position.line,
306
+ character: t.position.character + t.value.length
307
+ };
308
+ return isBetween(start, position, end);
309
+ });
310
+ return { tokensOnLine, index };
311
+ }
312
+ function isBetween(lb, t, ub) {
313
+ return lb.line <= t.line &&
314
+ lb.character <= t.character &&
315
+ ub.line >= t.line &&
316
+ ub.character >= t.character;
317
+ }
318
+ export function getCallTokens(tokensOnLine, index) {
319
+ const ret = [];
320
+ let current = getChildNode(tokensOnLine, index);
321
+ if (!current)
322
+ return ret;
323
+ while (current.parent && current.token) {
324
+ ret.unshift(current.token);
325
+ current = current.parent;
326
+ }
327
+ if (current.token)
328
+ ret.unshift(current.token);
329
+ return ret;
330
+ }
331
+ function getChildNode(tokensOnLine, index) {
332
+ const currentToken = tokensOnLine[index];
333
+ if (!currentToken)
334
+ return { token: undefined };
335
+ const previousToken = tokensOnLine[index - 1];
336
+ const nextToken = tokensOnLine[index + 1];
337
+ let routine = false;
338
+ if (previousToken) {
339
+ let newIndex = -1;
340
+ if (currentToken.isPeriod()) {
341
+ newIndex = resolve(tokensOnLine.slice(0, index));
342
+ }
343
+ else if (previousToken.isCaret()) {
344
+ routine = true;
345
+ }
346
+ else if (currentToken.isAlphanumeric() && previousToken.isPeriod()) {
347
+ newIndex = resolve(tokensOnLine.slice(0, index - 1));
348
+ }
349
+ if (newIndex >= 0) {
350
+ const parent = getChildNode(tokensOnLine, newIndex);
351
+ return { parent, token: currentToken };
352
+ }
353
+ }
354
+ if (nextToken && nextToken.isCaret()) {
355
+ const routineToken = tokensOnLine[index + 2];
356
+ if (!routineToken)
357
+ return undefined;
358
+ return { parent: { token: routineToken, routine: true }, token: currentToken };
359
+ }
360
+ if (currentToken.isAlphanumeric()) {
361
+ return { token: currentToken, routine };
362
+ }
363
+ return undefined;
364
+ }
365
+ export function resolve(tokens) {
366
+ const length = tokens.length;
367
+ let parenCount = 0;
368
+ if (length === 0)
369
+ return -1;
370
+ if (tokens[length - 1].isAlphanumeric())
371
+ return length - 1;
372
+ for (let index = tokens.length - 1; index >= 0; index--) {
373
+ const token = tokens[index];
374
+ if (token.isCloseParen())
375
+ parenCount++;
376
+ else if (token.isOpenParen())
377
+ parenCount--;
378
+ if (parenCount === 0) {
379
+ if (index > 0 && tokens[index - 1].isAlphanumeric())
380
+ return index - 1;
381
+ else
382
+ return -1;
383
+ }
384
+ }
385
+ return -1;
386
+ }
387
+ export function findCallable(tokensOnLine, index) {
388
+ const callables = [];
389
+ for (let tokenBufferIndex = 0; tokenBufferIndex <= index; tokenBufferIndex++) {
390
+ const token = tokensOnLine[tokenBufferIndex];
391
+ if (!tokenBufferIndex && !token.isTab() && !token.isSpace())
392
+ return null;
393
+ if (token.isOpenParen()) {
394
+ callables.push({
395
+ tokenBufferIndex: tokenBufferIndex - 1,
396
+ parameterIndex: 0
397
+ });
398
+ }
399
+ else if (token.isCloseParen()) {
400
+ if (callables.length)
401
+ callables.pop();
402
+ else
403
+ return null;
404
+ }
405
+ else if (token.isComma() && callables.length) {
406
+ callables[callables.length - 1].parameterIndex += 1;
407
+ }
408
+ }
409
+ if (!callables.length)
410
+ return null;
411
+ const activeCallable = callables.at(-1);
412
+ return {
413
+ callTokens: getCallTokens(tokensOnLine, activeCallable.tokenBufferIndex),
414
+ parameterIndex: activeCallable.parameterIndex,
415
+ };
416
+ }
417
+ export function getLineAfter(method) {
418
+ return method.closeParen ?
419
+ method.closeParen.position.line + 1 :
420
+ method.id.position.line + 1;
421
+ }
422
+ export function getCommentsOnLine(parsedDocument, lineNumber) {
423
+ return parsedDocument.comments.filter(t => {
424
+ return t.position.line === lineNumber;
425
+ });
426
+ }
427
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3V0aWxpdGllcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEtBQUssR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUNoQyxPQUFPLEtBQUssS0FBSyxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUU3QixPQUFPLEVBQVUsV0FBVyxFQUEwQixTQUFTLEVBQVksTUFBTSxVQUFVLENBQUM7QUFDNUYsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQVEsTUFBTSxhQUFhLENBQUM7QUFPcEQsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLElBQUksUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUVoRCxNQUFNLE9BQU8sZUFBZTtJQUUzQixjQUFjLENBQWlCO0lBQy9CLEtBQUssQ0FBYztJQUNuQixRQUFRLENBQVM7SUFFVCxTQUFTLEdBQWEsRUFBRSxDQUFDO0lBRWpDLFlBQ0MsY0FBOEIsRUFDOUIsS0FBa0IsRUFDbEIsd0JBQThEO1FBRTlELElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksd0JBQXdCO1lBQzNCLElBQUksQ0FBQyx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztRQUMxRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQUMsVUFBbUI7UUFDdEMsNEpBQTRKO1FBQzVKLDREQUE0RDtRQUM1RCxJQUFJLE1BQU0sR0FB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