UNPKG

eslint-plugin-sonarjs

Version:
74 lines (73 loc) • 3.46 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isAssertion = isAssertion; exports.isTSAssertion = isTSAssertion; exports.isTSAssertionWithAssignmentFallback = isTSAssertionWithAssignmentFallback; const typescript_1 = __importDefault(require("typescript")); const module_js_1 = require("../module.js"); const module_ts_js_1 = require("../module-ts.js"); const ASSERTIONS_MODULE = 'aws-cdk-lib/assertions'; const TEMPLATE_ASSERTION_METHOD_NAMES = new Set([ 'resourceCountIs', 'resourcePropertiesCountIs', 'hasResourceProperties', 'hasResource', 'allResources', 'allResourcesProperties', 'hasParameter', 'hasOutput', 'hasMapping', 'hasCondition', 'templateMatches', ]); const ASSERTION_METHODS_BY_FACTORY = new Map([ ['aws-cdk-lib.assertions.Template.fromStack', TEMPLATE_ASSERTION_METHOD_NAMES], ['aws-cdk-lib.assertions.Template.fromJSON', TEMPLATE_ASSERTION_METHOD_NAMES], ['aws-cdk-lib.assertions.Template.fromString', TEMPLATE_ASSERTION_METHOD_NAMES], [ 'aws-cdk-lib.assertions.Annotations.fromStack', new Set(['hasError', 'hasNoError', 'hasWarning', 'hasNoWarning', 'hasInfo', 'hasNoInfo']), ], ['aws-cdk-lib.assertions.Tags.fromStack', new Set(['hasValues', 'hasNone'])], ]); function isAssertion(context, node) { return node.type === 'CallExpression' && isFQNAssertion((0, module_js_1.getFullyQualifiedName)(context, node)); } function isTSAssertion(services, node) { if (node.kind !== typescript_1.default.SyntaxKind.CallExpression) { return false; } return isFQNAssertion((0, module_ts_js_1.getFullyQualifiedNameTS)(services, node)); } function isTSAssertionWithAssignmentFallback(context, services, node) { if (node.kind !== typescript_1.default.SyntaxKind.CallExpression) { return false; } // The ESTree fallback below resolves names by walking scopes on every call expression, so it is // gated on the file actually importing the module. `importsModuleTS` caches per source file. if (!(0, module_ts_js_1.importsModuleTS)(node.getSourceFile(), [ASSERTIONS_MODULE])) { return false; } // The type-aware resolver only follows declaration initializers. `isAssertion` delegates to // `getFullyQualifiedName`, whose ESTree scope resolver follows a variable's unique write, such // as an assertion object assigned in `beforeEach`. // The map only holds nodes converted from the linted file, so `undefined` here means `node` // belongs to another file (the caller follows calls into their implementation) and the // `context`-bound scope resolver could not be used on it anyway. The cast is the usual // TSESTree-to-ESTree widening: `isAssertion` only reads `type` and the shared node shape. const estreeNode = services.tsNodeToESTreeNodeMap.get(node); return estreeNode !== undefined && isAssertion(context, estreeNode); } function isFQNAssertion(fqn) { const normalized = fqn?.replaceAll('/', '.'); if (normalized === undefined) { return false; } const lastDot = normalized.lastIndexOf('.'); const factory = normalized.slice(0, lastDot); const method = normalized.slice(lastDot + 1); return ASSERTION_METHODS_BY_FACTORY.get(factory)?.has(method) ?? false; }