aboutsummaryrefslogtreecommitdiffstats
path: root/packages/tslint-config
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tslint-config')
-rw-r--r--packages/tslint-config/CHANGELOG.json9
-rw-r--r--packages/tslint-config/CHANGELOG.md4
-rw-r--r--packages/tslint-config/package.json7
-rw-r--r--packages/tslint-config/rules/booleanNamingRule.ts68
-rw-r--r--packages/tslint-config/rules/customNoMagicNumbersRule.ts76
-rw-r--r--packages/tslint-config/tslint.json3
6 files changed, 164 insertions, 3 deletions
diff --git a/packages/tslint-config/CHANGELOG.json b/packages/tslint-config/CHANGELOG.json
index ac59f7b19..4868b3983 100644
--- a/packages/tslint-config/CHANGELOG.json
+++ b/packages/tslint-config/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "timestamp": 1527009133,
+ "version": "0.4.18",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
"timestamp": 1525428773,
"version": "0.4.17",
"changes": [
diff --git a/packages/tslint-config/CHANGELOG.md b/packages/tslint-config/CHANGELOG.md
index 6f5042a52..56b65cadd 100644
--- a/packages/tslint-config/CHANGELOG.md
+++ b/packages/tslint-config/CHANGELOG.md
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v0.4.18 - _May 22, 2018_
+
+ * Dependencies updated
+
## v0.4.17 - _May 4, 2018_
* Dependencies updated
diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json
index 317ae4591..a64feb836 100644
--- a/packages/tslint-config/package.json
+++ b/packages/tslint-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@0xproject/tslint-config",
- "version": "0.4.17",
+ "version": "0.4.18",
"engines": {
"node": ">=6.12"
},
@@ -34,7 +34,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/tslint-config/README.md",
"devDependencies": {
- "@0xproject/monorepo-scripts": "^0.1.19",
+ "@0xproject/monorepo-scripts": "^0.1.20",
"@types/lodash": "4.14.104",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
@@ -45,7 +45,8 @@
"lodash": "^4.17.4",
"tslint": "5.8.0",
"tslint-eslint-rules": "^4.1.1",
- "tslint-react": "^3.2.0"
+ "tslint-react": "^3.2.0",
+ "tsutils": "2.22.2"
},
"publishConfig": {
"access": "public"
diff --git a/packages/tslint-config/rules/booleanNamingRule.ts b/packages/tslint-config/rules/booleanNamingRule.ts
new file mode 100644
index 000000000..a8e1dc390
--- /dev/null
+++ b/packages/tslint-config/rules/booleanNamingRule.ts
@@ -0,0 +1,68 @@
+import * as _ from 'lodash';
+import * as Lint from 'tslint';
+import * as ts from 'typescript';
+
+const VALID_BOOLEAN_PREFIXES = ['is', 'does', 'should', 'was', 'has', 'can', 'did', 'would', 'are'];
+
+export class Rule extends Lint.Rules.TypedRule {
+ public static FAILURE_STRING = `Boolean variable names should begin with: ${VALID_BOOLEAN_PREFIXES.join(', ')}`;
+
+ public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
+ return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
+ }
+}
+
+function walk(ctx: Lint.WalkContext<void>, tc: ts.TypeChecker): void {
+ traverse(ctx.sourceFile);
+
+ function traverse(node: ts.Node): void {
+ checkNodeForViolations(ctx, node, tc);
+ return ts.forEachChild(node, traverse);
+ }
+}
+
+function checkNodeForViolations(ctx: Lint.WalkContext<void>, node: ts.Node, tc: ts.TypeChecker): void {
+ switch (node.kind) {
+ // Handle: const { timestamp } = ...
+ case ts.SyntaxKind.BindingElement: {
+ const bindingElementNode = node as ts.BindingElement;
+ if (bindingElementNode.name.kind === ts.SyntaxKind.Identifier) {
+ handleBooleanNaming(bindingElementNode, tc, ctx);
+ }
+ break;
+ }
+
+ // Handle regular assignments: const block = ...
+ case ts.SyntaxKind.VariableDeclaration:
+ const variableDeclarationNode = node as ts.VariableDeclaration;
+ if (variableDeclarationNode.name.kind === ts.SyntaxKind.Identifier) {
+ handleBooleanNaming(node as ts.VariableDeclaration, tc, ctx);
+ }
+ break;
+
+ default:
+ _.noop();
+ }
+}
+
+function handleBooleanNaming(
+ node: ts.VariableDeclaration | ts.BindingElement,
+ tc: ts.TypeChecker,
+ ctx: Lint.WalkContext<void>,
+): void {
+ const nodeName = node.name;
+ const variableName = nodeName.getText();
+ const lowercasedName = _.toLower(variableName);
+ const typeNode = tc.getTypeAtLocation(node);
+ const typeName = (typeNode as any).intrinsicName;
+ if (typeName === 'boolean') {
+ const hasProperName = !_.isUndefined(
+ _.find(VALID_BOOLEAN_PREFIXES, prefix => {
+ return _.startsWith(lowercasedName, prefix);
+ }),
+ );
+ if (!hasProperName) {
+ ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
+ }
+ }
+}
diff --git a/packages/tslint-config/rules/customNoMagicNumbersRule.ts b/packages/tslint-config/rules/customNoMagicNumbersRule.ts
new file mode 100644
index 000000000..e358221eb
--- /dev/null
+++ b/packages/tslint-config/rules/customNoMagicNumbersRule.ts
@@ -0,0 +1,76 @@
+import * as Lint from 'tslint';
+import { isPrefixUnaryExpression } from 'tsutils';
+import * as ts from 'typescript';
+
+/**
+ * A modified version of the no-magic-numbers rule that allows for magic numbers
+ * when instantiating a BigNumber instance.
+ * E.g We want to be able to write:
+ * const amount = new BigNumber(5);
+ * Original source: https://github.com/palantir/tslint/blob/42b058a6baa688f8be8558b277eb056c3ff79818/src/rules/noMagicNumbersRule.ts
+ */
+export class Rule extends Lint.Rules.AbstractRule {
+ public static ALLOWED_NODES = new Set<ts.SyntaxKind>([
+ ts.SyntaxKind.ExportAssignment,
+ ts.SyntaxKind.FirstAssignment,
+ ts.SyntaxKind.LastAssignment,
+ ts.SyntaxKind.PropertyAssignment,
+ ts.SyntaxKind.ShorthandPropertyAssignment,
+ ts.SyntaxKind.VariableDeclaration,
+ ts.SyntaxKind.VariableDeclarationList,
+ ts.SyntaxKind.EnumMember,
+ ts.SyntaxKind.PropertyDeclaration,
+ ts.SyntaxKind.Parameter,
+ ]);
+
+ public static DEFAULT_ALLOWED = [-1, 0, 1];
+
+ public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
+ const allowedNumbers = this.ruleArguments.length > 0 ? this.ruleArguments : Rule.DEFAULT_ALLOWED;
+ return this.applyWithWalker(
+ new CustomNoMagicNumbersWalker(sourceFile, this.ruleName, new Set(allowedNumbers.map(String))),
+ );
+ }
+}
+
+// tslint:disable-next-line:max-classes-per-file
+class CustomNoMagicNumbersWalker extends Lint.AbstractWalker<Set<string>> {
+ public static FAILURE_STRING = "'magic numbers' are not allowed";
+ private static _isNegativeNumberLiteral(
+ node: ts.Node,
+ ): node is ts.PrefixUnaryExpression & { operand: ts.NumericLiteral } {
+ return (
+ isPrefixUnaryExpression(node) &&
+ node.operator === ts.SyntaxKind.MinusToken &&
+ node.operand.kind === ts.SyntaxKind.NumericLiteral
+ );
+ }
+ public walk(sourceFile: ts.SourceFile): void {
+ const cb = (node: ts.Node): void => {
+ if (node.kind === ts.SyntaxKind.NumericLiteral) {
+ return this.checkNumericLiteral(node, (node as ts.NumericLiteral).text);
+ }
+ if (CustomNoMagicNumbersWalker._isNegativeNumberLiteral(node)) {
+ return this.checkNumericLiteral(node, `-${(node.operand as ts.NumericLiteral).text}`);
+ }
+ return ts.forEachChild(node, cb);
+ };
+ return ts.forEachChild(sourceFile, cb);
+ }
+
+ // tslint:disable:no-non-null-assertion
+ // tslint:disable-next-line:underscore-private-and-protected
+ private checkNumericLiteral(node: ts.Node, num: string): void {
+ if (!Rule.ALLOWED_NODES.has(node.parent!.kind) && !this.options.has(num)) {
+ if (node.parent!.kind === ts.SyntaxKind.NewExpression) {
+ const className = (node.parent! as any).expression.escapedText;
+ const BIG_NUMBER_NEW_EXPRESSION = 'BigNumber';
+ if (className === BIG_NUMBER_NEW_EXPRESSION) {
+ return; // noop
+ }
+ }
+ this.addFailureAtNode(node, CustomNoMagicNumbersWalker.FAILURE_STRING);
+ }
+ }
+ // tslint:enable:no-non-null-assertion
+}
diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json
index 1d717430d..77a1f41cc 100644
--- a/packages/tslint-config/tslint.json
+++ b/packages/tslint-config/tslint.json
@@ -5,7 +5,10 @@
"arrow-parens": [true, "ban-single-arg-parens"],
"arrow-return-shorthand": true,
"async-suffix": true,
+ "boolean-naming": true,
+ "no-switch-case-fall-through": true,
"await-promise": true,
+ "custom-no-magic-numbers": [true, 0, 1, 2, 3, -1],
"binary-expression-operand-order": true,
"callable-types": true,
"class-name": true,