tsd
Version:
Check TypeScript type definitions
89 lines (88 loc) • 3.24 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseErrorAssertionToLocation = exports.extractAssertions = void 0;
const typescript_1 = require("@tsd/typescript");
const assertions_1 = require("./assertions");
const assertionFnNames = new Set(Object.values(assertions_1.Assertion));
/**
* Extract all assertions.
*
* @param program - TypeScript program.
*/
const extractAssertions = (program) => {
const assertions = new Map();
const checker = program.getTypeChecker();
/**
* Checks if the given node is semantically valid and is an assertion.
*/
function handleNode(node) {
var _a;
const expression = (0, typescript_1.isPropertyAccessExpression)(node.expression) ?
node.expression.name :
node.expression;
const maybeSymbol = checker.getSymbolAtLocation(expression);
if (!maybeSymbol) {
// Bail out if a Symbol doesn't exist for this Node
// This either means a symbol could not be resolved
// for an identifier, or that the expression is
// syntactically valid, but not semantically valid.
return;
}
const symbol = maybeSymbol.flags & typescript_1.SymbolFlags.Alias ?
checker.getAliasedSymbol(maybeSymbol) :
maybeSymbol;
const identifier = symbol.getName();
// Check if the call type is a valid assertion
if (assertionFnNames.has(identifier)) {
const assertion = identifier;
const nodes = (_a = assertions.get(assertion)) !== null && _a !== void 0 ? _a : new Set();
nodes.add(node);
assertions.set(assertion, nodes);
}
}
/**
* Recursively loop over all the nodes and extract all the assertions out of the source files.
*/
function walkNodes(node) {
if ((0, typescript_1.isCallExpression)(node)) {
handleNode(node);
}
(0, typescript_1.forEachChild)(node, walkNodes);
}
for (const sourceFile of program.getSourceFiles()) {
walkNodes(sourceFile);
}
return assertions;
};
exports.extractAssertions = extractAssertions;
/**
* Loop over all the error assertion nodes and convert them to a location map.
*
* @param assertions - Assertion map.
*/
const parseErrorAssertionToLocation = (assertions) => {
const nodes = assertions.get(assertions_1.Assertion.EXPECT_ERROR);
const expectedErrors = new Map();
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() + 1
};
const pos = node
.getSourceFile()
.getLineAndCharacterOfPosition(node.getStart());
expectedErrors.set(location, {
fileName: location.fileName,
line: pos.line + 1,
column: pos.character
});
}
return expectedErrors;
};
exports.parseErrorAssertionToLocation = parseErrorAssertionToLocation;
;