forked from tsdjs/tsd
/
parser.ts
83 lines (65 loc) · 2.12 KB
/
parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import {Program, Node, CallExpression, forEachChild, isCallExpression, Identifier} from '@tsd/typescript';
import {Assertion} from './assertions';
import {Location, Diagnostic} from './interfaces';
const assertionFnNames = new Set<string>(Object.values(Assertion));
/**
* Extract all assertions.
*
* @param program - TypeScript program.
*/
export const extractAssertions = (program: Program): Map<Assertion, Set<CallExpression>> => {
const assertions = new Map<Assertion, Set<CallExpression>>();
/**
* Recursively loop over all the nodes and extract all the assertions out of the source files.
*/
function walkNodes(node: Node) {
if (isCallExpression(node)) {
const identifier = (node.expression as Identifier).getText();
// Check if the call type is a valid assertion
if (assertionFnNames.has(identifier)) {
const assertion = identifier as Assertion;
const nodes = assertions.get(assertion) || new Set<CallExpression>();
nodes.add(node);
assertions.set(assertion, nodes);
}
}
forEachChild(node, walkNodes);
}
for (const sourceFile of program.getSourceFiles()) {
walkNodes(sourceFile);
}
return assertions;
};
export type ExpectedError = Pick<Diagnostic, 'fileName' | 'line' | 'column'>;
/**
* Loop over all the error assertion nodes and convert them to a location map.
*
* @param assertions - Assertion map.
*/
export const parseErrorAssertionToLocation = (
assertions: Map<Assertion, Set<CallExpression>>
): Map<Location, ExpectedError> => {
const nodes = assertions.get(Assertion.EXPECT_ERROR);
const expectedErrors = new Map<Location, ExpectedError>();
if (!nodes) {
// Bail out if we don't have any error nodes
return expectedErrors;
}
// Iterate over the nodes and add the node range to the map
for (const node of nodes) {
const location = {
fileName: node.getSourceFile().fileName,
start: node.getStart(),
end: node.getEnd()
};
const pos = node
.getSourceFile()
.getLineAndCharacterOfPosition(node.getStart());
expectedErrors.set(location, {
fileName: location.fileName,
line: pos.line + 1,
column: pos.character
});
}
return expectedErrors;
};