eslint-plugin-sonarjs
Version:
69 lines (68 loc) • 2.99 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TYPE_LEVEL_ROOTS = void 0;
exports.isAssertion = isAssertion;
exports.isTSAssertion = isTSAssertion;
exports.isTSSetupCall = isTSSetupCall;
const module_js_1 = require("./module.js");
const module_ts_js_1 = require("./module-ts.js");
const typescript_1 = __importDefault(require("typescript"));
function isAssertion(context, node) {
const fullyQualifiedName = extractFQNforCallExpression(context, node);
return isFQNAssertion(fullyQualifiedName);
}
function isTSAssertion(services, node) {
if (node.kind !== typescript_1.default.SyntaxKind.CallExpression) {
return false;
}
const fqn = (0, module_ts_js_1.getFullyQualifiedNameTS)(services, node);
return isFQNAssertion(fqn);
}
// Vitest's compile-time type checks: never executed at runtime, idiomatic at top
// level in .test-d.ts files, so rules about assertion placement must not flag them.
exports.TYPE_LEVEL_ROOTS = ['vitest.expectTypeOf', 'vitest.assertType'];
// The set of valid matchers is open (custom matchers, matchers called on a stored
// result), so we cannot enumerate them. Instead, we match anything under these
// roots and then exclude the few non-assertion members below.
const ASSERTION_ROOTS = ['vitest.expect', ...exports.TYPE_LEVEL_ROOTS];
// Static helpers on `expect` that share the `vitest.expect` root but configure or
// declare rather than assert. This set IS closed, so we carve it out by name.
const NON_ASSERTION_EXPECT_MEMBERS = new Set([
'extend',
'addEqualityTesters',
'addSnapshotSerializer',
'getState',
'setState',
'assertions',
'hasAssertions',
]);
function isFQNAssertion(fqn) {
if (!fqn || !ASSERTION_ROOTS.some(root => fqn === root || fqn.startsWith(`${root}.`))) {
return false;
}
const [, namespace, member] = fqn.split('.');
return !(namespace === 'expect' && NON_ASSERTION_EXPECT_MEMBERS.has(member));
}
/**
* Whether `node` is a call to a vitest `expect` setup/config helper
* (`expect.extend`, `addSnapshotSerializer`, …). These are not runtime assertions
* (see {@link isFQNAssertion}), but their arguments are type-checked — so under the
* type-checker they act as compile-time checks. Type-aware callers may treat them
* as such.
*/
function isTSSetupCall(services, node) {
if (node.kind !== typescript_1.default.SyntaxKind.CallExpression) {
return false;
}
const [, namespace, member] = ((0, module_ts_js_1.getFullyQualifiedNameTS)(services, node) ?? '').split('.');
return namespace === 'expect' && NON_ASSERTION_EXPECT_MEMBERS.has(member);
}
function extractFQNforCallExpression(context, node) {
if (node.type !== 'CallExpression') {
return undefined;
}
return (0, module_js_1.getFullyQualifiedName)(context, node);
}