Skip to content

Commit

Permalink
convert no-stateless-class-rule to use a walk function (microsoft#766)
Browse files Browse the repository at this point in the history
  • Loading branch information
drexler authored and apawast committed Feb 26, 2019
1 parent 8d2afa1 commit e92f107
Showing 1 changed file with 24 additions and 22 deletions.
46 changes: 24 additions & 22 deletions src/noStatelessClassRule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ts from 'typescript';
import * as Lint from 'tslint';
import * as tsutils from 'tsutils';

import { AstUtils } from './utils/AstUtils';
import { Utils } from './utils/Utils';
Expand Down Expand Up @@ -31,35 +32,23 @@ export class Rule extends Lint.Rules.AbstractRule {
console.warn('Warning: no-stateless-class rule is deprecated. Replace your usage with the TSLint no-unnecessary-class rule.');
Rule.isWarningShown = true;
}
return this.applyWithWalker(new NoStatelessClassRuleWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}

class NoStatelessClassRuleWalker extends Lint.RuleWalker {
protected visitClassDeclaration(node: ts.ClassDeclaration): void {
if (!this.isClassStateful(node)) {
const className: string = node.name === undefined ? '<unknown>' : node.name.text;
this.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING + className);
}
super.visitClassDeclaration(node);
}

private isClassStateful(node: ts.ClassDeclaration): boolean {
if (this.classExtendsSomething(node)) {
function walk(ctx: Lint.WalkContext<void>) {
function isClassStateful(node: ts.ClassDeclaration): boolean {
if (classExtendsSomething(node) || classDeclaresConstructorProperties(node)) {
return true;
}
if (node.members.length === 0) {
return false;
}

if (this.classDeclaresConstructorProperties(node)) {
return true;
}

return this.classDeclaresInstanceData(node);
return classDeclaresInstanceData(node);
}

private classDeclaresInstanceData(node: ts.ClassDeclaration): boolean {
function classDeclaresInstanceData(node: ts.ClassDeclaration): boolean {
return Utils.exists(
node.members,
(classElement: ts.ClassElement): boolean => {
Expand All @@ -74,19 +63,19 @@ class NoStatelessClassRuleWalker extends Lint.RuleWalker {
);
}

private classDeclaresConstructorProperties(node: ts.ClassDeclaration): boolean {
function classDeclaresConstructorProperties(node: ts.ClassDeclaration): boolean {
return Utils.exists(
node.members,
(element: ts.ClassElement): boolean => {
if (element.kind === ts.SyntaxKind.Constructor) {
return this.constructorDeclaresProperty(<ts.ConstructorDeclaration>element);
return constructorDeclaresProperty(<ts.ConstructorDeclaration>element);
}
return false;
}
);
}

private constructorDeclaresProperty(ctor: ts.ConstructorDeclaration): boolean {
function constructorDeclaresProperty(ctor: ts.ConstructorDeclaration): boolean {
return Utils.exists(
ctor.parameters,
(param: ts.ParameterDeclaration): boolean => {
Expand All @@ -104,12 +93,25 @@ class NoStatelessClassRuleWalker extends Lint.RuleWalker {
);
}

private classExtendsSomething(node: ts.ClassDeclaration): boolean {
function classExtendsSomething(node: ts.ClassDeclaration): boolean {
return Utils.exists(
node.heritageClauses,
(clause: ts.HeritageClause): boolean => {
return clause.token === ts.SyntaxKind.ExtendsKeyword;
}
);
}

function cb(node: ts.Node): void {
if (tsutils.isClassDeclaration(node)) {
if (!isClassStateful(node)) {
const className: string = node.name === undefined ? '<unknown>' : node.name.text;
ctx.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STRING + className);
}
}

return ts.forEachChild(node, cb);
}

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

0 comments on commit e92f107

Please sign in to comment.