Skip to content

Commit

Permalink
Converted no-increment-decrement to use a walk function. (microsoft#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
reduckted authored and apawast committed Feb 26, 2019
1 parent 6e8e262 commit ae46152
Showing 1 changed file with 43 additions and 36 deletions.
79 changes: 43 additions & 36 deletions src/noIncrementDecrementRule.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import * as ts from 'typescript';
import * as Lint from 'tslint';
import * as tsutils from 'tsutils';

import { ExtendedMetadata } from './utils/ExtendedMetadata';

const OPTION_ALLOW_FOR_LOOPS = 'allow-for-loops';

interface Options {
allowForLoops: boolean;
}

/**
* Implementation of the no-increment-decrement rule.
*/
Expand Down Expand Up @@ -44,51 +49,53 @@ export class Rule extends Lint.Rules.AbstractRule {
Rule.isWarningShown = true;
}

return this.applyWithWalker(new NoIncrementDecrementWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions()));
}
}

class NoIncrementDecrementWalker extends Lint.RuleWalker {
private readonly allowForLoops: boolean;

constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) {
super(sourceFile, options);

this.allowForLoops = options.ruleArguments.indexOf(OPTION_ALLOW_FOR_LOOPS) > -1;
private parseOptions(options: Lint.IOptions): Options {
return {
allowForLoops: options.ruleArguments.indexOf(OPTION_ALLOW_FOR_LOOPS) > -1
};
}
}

protected visitForStatement(node: ts.ForStatement): void {
if (this.allowForLoops) {
// If for loops are allowed to contain increment and decrement,
// check everything except the incrementor
super.visitNode(node.statement);
if (node.initializer) {
super.visitNode(node.initializer);
}
if (node.condition) {
super.visitNode(node.condition);
}
} else {
// Otherwise check the node
super.visitForStatement(node);
function walk(ctx: Lint.WalkContext<Options>) {
function validateUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) {
if (node.operator === ts.SyntaxKind.PlusPlusToken) {
ctx.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden ++ operator');
} else if (node.operator === ts.SyntaxKind.MinusMinusToken) {
ctx.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden -- operator');
}
}

protected visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression): void {
this.validateUnaryExpression(node);
super.visitPostfixUnaryExpression(node);
}
function cb(node: ts.Node): void {
if (tsutils.isForStatement(node)) {
if (ctx.options.allowForLoops) {
// If for loops are allowed to contain increment and decrement,
// check everything except the incrementor
cb(node.statement);
if (node.initializer) {
cb(node.initializer);
}
if (node.condition) {
cb(node.condition);
}
} else {
// Otherwise check the node
ts.forEachChild(node, cb);
}

protected visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression): void {
this.validateUnaryExpression(node);
super.visitPrefixUnaryExpression(node);
}
return;
}

private validateUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) {
if (node.operator === ts.SyntaxKind.PlusPlusToken) {
this.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden ++ operator');
} else if (node.operator === ts.SyntaxKind.MinusMinusToken) {
this.addFailureAt(node.getStart(), node.getWidth(), 'Forbidden -- operator');
if (tsutils.isPostfixUnaryExpression(node)) {
validateUnaryExpression(node);
} else if (tsutils.isPrefixUnaryExpression(node)) {
validateUnaryExpression(node);
}

return ts.forEachChild(node, cb);
}

return ts.forEachChild(ctx.sourceFile, cb);
}

0 comments on commit ae46152

Please sign in to comment.