eslint-plugin-ferramentas
Version:
A bundle of useful ESLint rules
144 lines (143 loc) • 5.96 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRule = exports.createBaseRuleOptionInputMapper = void 0;
const assert_1 = __importDefault(require("assert"));
const path_1 = require("path");
const utils_1 = require("../utils");
const createBaseRuleOptionInputMapper = (mapper) => ([input]) => mapper(input);
exports.createBaseRuleOptionInputMapper = createBaseRuleOptionInputMapper;
const relativeToWorkingDirectory = (context, absolutePath) => (0, path_1.relative)(context.cwd, absolutePath);
class ExtendedNode {
static getProperty(node, property) {
const value = node[property];
(0, assert_1.default)(value !== undefined, `Expected property '${String(property)}' can not be undefined`);
return value;
}
static sortPositions([...positions]) {
return positions.sort(({ start: aStart }, { start: bStart }) => {
let diff = 0;
for (const prop of ['line', 'column']) {
diff = aStart[prop] - bStart[prop];
if (diff !== 0) {
break;
}
}
return diff;
});
}
constructor(node, context) {
this.node = node;
this.context = context;
this.getFirstComment = (0, utils_1.createExecuteOnce)(() => this.sourceCode.getCommentsBefore(this.node)[0] ?? null);
}
get sourceCode() {
return this.context.sourceCode;
}
getProperty(prop, withComments) {
const nodeValue = ExtendedNode.getProperty(this.node, prop);
if (!withComments) {
return [nodeValue, null];
}
const firstComment = this.getFirstComment();
return [nodeValue, firstComment === null ? null : ExtendedNode.getProperty(firstComment, prop)];
}
getPreviousSiblingWithSameTypeOrThrow() {
const { siblings } = this;
const currentIndex = siblings.indexOf(this.node);
const previousSibling = siblings[currentIndex - 1];
(0, assert_1.default)(previousSibling !== undefined && this.isNode(previousSibling), 'Previous import declaration could not be found');
return new this.NodeConstructor(previousSibling, this.context);
}
getLocation(withComments) {
const [loc, commentLoc] = this.getProperty('loc', withComments);
(0, assert_1.default)(loc !== null, 'Location was not expected to be null');
return commentLoc === null ? loc : { ...loc, start: ExtendedNode.sortPositions([loc, commentLoc])[0].start };
}
getRange(withComments) {
const [range, commentRange] = this.getProperty('range', withComments);
return commentRange === null ? range : [commentRange[0], range[1]];
}
getRangeBetween(destination, withComments) {
const thisLocation = this.getLocation(withComments);
const destinationLocation = destination.getLocation(withComments);
const [first, second] = ExtendedNode.sortPositions([thisLocation, destinationLocation]);
return [this.sourceCode.getIndexFromLoc(first.end), this.sourceCode.getIndexFromLoc(second.start)];
}
toString(withComments = true) {
let offset = 0;
if (withComments) {
const [startWithComments] = this.getRange(true);
const [startWithoutComments] = this.getRange(false);
offset = startWithoutComments - startWithComments;
}
return this.sourceCode.getText(this.node, offset);
}
}
class ExtendedImportDeclaration extends ExtendedNode {
constructor() {
super(...arguments);
this.NodeConstructor = ExtendedImportDeclaration;
this.getRawPath = (0, utils_1.createExecuteOnce)(() => {
const { value } = this.node.source;
(0, assert_1.default)(typeof value === 'string', `Import path '${String(value)}' should be a string`);
return value;
});
this.getPathFromWorkingDirectory = (0, utils_1.createExecuteOnce)(() => {
const absolutePath = (0, path_1.resolve)((0, path_1.dirname)(this.context.filename), this.rawPath);
return relativeToWorkingDirectory(this.context, absolutePath);
});
}
get siblings() {
return this.sourceCode.ast.body;
}
get rawPath() {
return this.getRawPath();
}
get pathFromWorkingDirectory() {
return this.getPathFromWorkingDirectory();
}
isNode(node) {
return node.type === 'ImportDeclaration';
}
getPreviousSiblingWithSameTypeOrThrow() {
return super.getPreviousSiblingWithSameTypeOrThrow();
}
}
class RuleContextWrapper {
constructor(context, ruleName, mapOptions) {
this.context = context;
this.ruleName = ruleName;
this.mapOptions = mapOptions;
this.getOptions = (0, utils_1.createExecuteOnce)(() => this.mapOptions(this.context.options));
this.createDebugger = (0, utils_1.createExecuteOnce)(() => (0, utils_1.createDebugger)(this.getOption('debug')));
}
getRelativeFilename() {
return relativeToWorkingDirectory(this.context, this.context.filename);
}
getImportDeclaration(node) {
return new ExtendedImportDeclaration(node, this.context);
}
getOption(name) {
return this.getOptions()[name];
}
debug(...values) {
const debug = this.createDebugger();
debug(...values.map((v) => v.toString()));
}
report(descriptor) {
this.context.report(descriptor);
}
}
const createRule = ({ name, ...meta }, mapOptions, create) => ({
[name]: {
meta: { ...meta },
create: (context) => {
const contextWrapper = new RuleContextWrapper(context, name, mapOptions);
return create(contextWrapper);
},
},
});
exports.createRule = createRule;