eslint-plugin-sonarjs
Version:
64 lines (63 loc) • 2.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInsideVueSetupScript = isInsideVueSetupScript;
exports.isVue2OrEarlier = isVue2OrEarlier;
exports.getVueReactiveBindingKind = getVueReactiveBindingKind;
const semver_1 = require("semver");
const dependencies_js_1 = require("./dependency-manifests/dependencies.js");
const ast_js_1 = require("./ast.js");
const module_js_1 = require("./module.js");
// "-0" makes the lower bound prerelease-inclusive, so an exact pin like "3.0.0-rc.13" still counts as Vue 3+
const VUE_3_OR_LATER_RANGE = '>=3.0.0-0';
const VUE_REF_FQN = 'vue.ref';
const VUE_REACTIVE_FQN = 'vue.reactive';
function isVueSetupScript(element) {
return (element.type === 'VElement' &&
element.name === 'script' &&
element.startTag.attributes.some(attr => attr.key.name === 'setup'));
}
function isInsideVueSetupScript(node, ctx) {
const doc = ctx.sourceCode.parserServices?.getDocumentFragment?.();
const setupScript = doc?.children.find(isVueSetupScript);
return (!!setupScript &&
!!node.range &&
setupScript.range[0] <= node.range[0] &&
setupScript.range[1] >= node.range[1]);
}
/** Returns true when no Vue dependency is declared, or a declared parseable range provably excludes Vue 3+; an unparseable range (workspace:, catalog:, git:) keeps reporting, unlike a missing dependency. */
function isVue2OrEarlier(context) {
const vueVersionRange = (0, dependencies_js_1.getVueVersion)(context);
if (!vueVersionRange) {
return true;
}
if (!(0, semver_1.validRange)(vueVersionRange)) {
return false;
}
return !(0, semver_1.intersects)(vueVersionRange, VUE_3_OR_LATER_RANGE);
}
/**
* Resolves `identifier` to the variable it references and, if that variable is initialized by a
* call to `ref()` or `reactive()` imported from 'vue', returns which one. Used to recognize
* mutations of tracked reactive state without requiring the enclosing code to be independently
* proven to be a Vue component: an import-resolved `ref`/`reactive` binding is itself a strong
* enough Vue signal.
*/
function getVueReactiveBindingKind(context, identifier) {
const variable = (0, ast_js_1.getVariableFromName)(context, identifier.name, identifier);
const definition = variable?.defs[0];
if (definition?.type !== 'Variable') {
return undefined;
}
const init = definition.node.init;
if (init?.type !== 'CallExpression') {
return undefined;
}
const fqn = (0, module_js_1.getFullyQualifiedName)(context, init);
if (fqn === VUE_REF_FQN) {
return 'ref';
}
if (fqn === VUE_REACTIVE_FQN) {
return 'reactive';
}
return undefined;
}