@equisoft/tslint-config
Version:
Equisoft's TSLint configuration.
112 lines (111 loc) • 4.91 kB
JavaScript
"use strict";
/**
* This rule is a copy of tslint-eslint-rules:
*
* source file: https://github.com/buzinas/tslint-eslint-rules/blob/master/src/rules/objectCurlySpacingRule.ts
* git commit hash: 24190b7059b8c947d7df5b731434566fdd6b5468
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Rule = void 0;
const Lint = require("tslint");
const ts = require("typescript");
const OPTION_ALWAYS = 'always';
class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile) {
const walker = new ObjectCurlySpacingWalker(sourceFile, this.getOptions());
return this.applyWithWalker(walker);
}
}
exports.Rule = Rule;
Rule.FAILURE_STRING = {
always: {
start: `A space is required after '{'`,
end: `A space is required before '}'`,
},
never: {
start: `There should be no space after '{'`,
end: `There should be no space before '}'`,
},
};
class ObjectCurlySpacingWalker extends Lint.RuleWalker {
constructor(sourceFile, options) {
super(sourceFile, options);
const opt = this.getOptions();
this.always = this.hasOption(OPTION_ALWAYS) || (opt && opt.length === 0);
this.exceptions = opt[1] || {};
if (this.exceptions.arraysInObjects === undefined) {
this.exceptions.arraysInObjects = this.always;
}
if (this.exceptions.objectsInObjects === undefined) {
this.exceptions.objectsInObjects = this.always;
}
}
visitNode(node) {
const bracedKind = [
ts.SyntaxKind.ObjectLiteralExpression,
ts.SyntaxKind.ObjectBindingPattern,
ts.SyntaxKind.NamedImports,
ts.SyntaxKind.NamedExports,
];
if (bracedKind.indexOf(node.kind) > -1) {
this.checkSpacingInsideBraces(node);
}
super.visitNode(node);
}
checkSpacingInsideBraces(node) {
const text = node.getText();
if (text.indexOf('\n') !== -1 || /^\{\s*\}$/.test(text)) {
// Rule does not apply when the braces span multiple lines
return;
}
// Lookup whether the last value in the object is an object or array literal
let endsWithObjectLiteral = false;
let endsWithArrayLiteral = false;
if (node.getChildren().length === 3) {
const contents = node.getChildren()[1].getChildren();
if (contents.length > 0) {
const lastElement = contents[contents.length - 1];
if (lastElement.kind === ts.SyntaxKind.PropertyAssignment || lastElement.kind
=== ts.SyntaxKind.BindingElement) {
const value = lastElement.getChildren();
if (value.length === 3) {
endsWithObjectLiteral = value[2].kind === ts.SyntaxKind.ObjectLiteralExpression || value[2].kind
=== ts.SyntaxKind.ObjectBindingPattern;
endsWithArrayLiteral = value[2].kind === ts.SyntaxKind.ArrayLiteralExpression;
}
}
}
}
// We have matching braces, lets find out number of leading spaces
const leadingSpace = text.match(/^\{(\s{0,2})/)[1].length;
if (this.always) {
if (leadingSpace === 0) {
const fix = Lint.Replacement.appendText(node.getStart() + 1, ' ');
this.addFailure(this.createFailure(node.getStart(), 1, Rule.FAILURE_STRING.always.start, fix));
}
}
else {
if (leadingSpace > 0) {
const fix = Lint.Replacement.deleteText(node.getStart() + 1, leadingSpace);
this.addFailure(this.createFailure(node.getStart(), 1, Rule.FAILURE_STRING.never.start, fix));
}
}
// Finding trailing spaces requires checking if exceptions apply, and adjusting accordingly
const trailingSpace = text.match(/(\s{0,2})}$/)[1].length;
const arrayExceptionApplies = this.always !== this.exceptions.arraysInObjects && endsWithArrayLiteral;
const objectExceptionApplies = this.always !== this.exceptions.objectsInObjects && endsWithObjectLiteral;
const spaceRequired = arrayExceptionApplies || objectExceptionApplies ? !this.always : this.always;
if (spaceRequired) {
if (trailingSpace === 0) {
const fix = Lint.Replacement.appendText(node.getEnd() - 1, ' ');
this.addFailure(this.createFailure(node.getEnd() - 1, 1, Rule.FAILURE_STRING.always.end, fix));
}
}
else {
if (trailingSpace > 0) {
const fix = Lint.Replacement.deleteText(node.getEnd() - trailingSpace - 1, trailingSpace);
this.addFailure(this.createFailure(node.getEnd() - 1, 1, Rule.FAILURE_STRING.never.end, fix));
}
}
}
}