Skip to content
114 changes: 114 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"prettier-check": "diffs=$(prettier --list-different '{src,tests,types,examples,docs}/**/*.ts?(x)'); if [ ! -z $diffs ]; then echo \"Run 'npm run prettier'\nThe following files need formatting:\n$diffs\" && exit 1; fi;",
"tests": "jest",
"test": "npm run lint && npm run tests -- --runInBand --coverage",
"prettier": "prettier --write '{src,tests,types,examples,docs}/**/*.ts?(x)'"
"prettier": "prettier --write '{src,tests,types,examples,docs}/**/*.ts?(x)'",
"test-files": "npm run dist && tslint --project tsconfig.json 'test-files/**/*.@(ts|tsx)'",
"prepublishOnly": "npm run dist"
},
"repository": {
"type": "git",
Expand All @@ -37,8 +39,13 @@
},
"devDependencies": {
"@types/jest": "^23.3.2",
"@types/node": "^10.10.3",
"@types/react": "^16.4.14",
"@types/react-redux": "^6.0.9",
"jest": "^23.6.0",
"prettier": "^1.14.2",
"react": "^16.5.2",
"react-redux": "^5.0.7",
"ts-jest": "^23.10.1",
"tslint": "^5.11.0",
"tslint-config-dabapps": "github:dabapps/tslint-config-dabapps#v0.5.1"
Expand Down
21 changes: 21 additions & 0 deletions src/__reference-rule__.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Lint from 'tslint';
import * as ts from 'typescript';

const FAILURE_STRING = 'Import statements are disallowed';

// The walker takes care of all the work.
class NoImportsWalker extends Lint.RuleWalker {
public visitImportDeclaration (node: ts.ImportDeclaration) {
// create a failure at the current position
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), FAILURE_STRING));

// call the base version of this visitor to actually parse this node
super.visitImportDeclaration(node);
}
}

export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoImportsWalker(sourceFile, this.getOptions()));
}
}
4 changes: 1 addition & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export const message = 'Hello, World!';

export default message;
export = { rulesDirectory: '.' };
55 changes: 55 additions & 0 deletions src/noPropIntersectionRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as Lint from 'tslint';
import * as ts from 'typescript';

const FAILURE_STRING = 'Props must not be an intersection in Component or PureComponent params';

// The walker takes care of all the work.
class NoPropIntersectionWalker extends Lint.RuleWalker {
public visitClassDeclaration (node: ts.ClassDeclaration) {
if (node.heritageClauses && node.heritageClauses.length) {
node.heritageClauses.forEach((heritage) => {
heritage.forEachChild((child) => {
if (child.kind === ts.SyntaxKind.ExpressionWithTypeArguments) {
this.checkExpression(child as ts.ExpressionWithTypeArguments);
}
});
});
}

// call the base version of this visitor to actually parse this node
super.visitClassDeclaration(node);
}

private getExpressionName (node: ts.ExpressionWithTypeArguments) {
if (ts.isIdentifier(node.expression)) {
return (node.expression as ts.Identifier).escapedText;
} else if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
return (node.expression as ts.PropertyAccessExpression).name.escapedText;
}

return '';
}

private checkExpression (node: ts.ExpressionWithTypeArguments) {
const name = this.getExpressionName(node);

if (name === 'PureComponent' || name === 'Component') {
const { typeArguments } = node;

if (typeArguments) {
typeArguments.forEach((typeArgument) => {
if (typeArgument.kind === ts.SyntaxKind.IntersectionType) {
// create a failure at the current position
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), FAILURE_STRING));
}
});
}
}
}
}

export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoPropIntersectionWalker(sourceFile, this.getOptions()));
}
}
55 changes: 55 additions & 0 deletions src/noPropUnionRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as Lint from 'tslint';
import * as ts from 'typescript';

const FAILURE_STRING = 'Props must not be an union in Component or PureComponent params';

// The walker takes care of all the work.
class NoPropUnionWalker extends Lint.RuleWalker {
public visitClassDeclaration (node: ts.ClassDeclaration) {
if (node.heritageClauses && node.heritageClauses.length) {
node.heritageClauses.forEach((heritage) => {
heritage.forEachChild((child) => {
if (child.kind === ts.SyntaxKind.ExpressionWithTypeArguments) {
this.checkExpression(child as ts.ExpressionWithTypeArguments);
}
});
});
}

// call the base version of this visitor to actually parse this node
super.visitClassDeclaration(node);
}

private getExpressionName (node: ts.ExpressionWithTypeArguments) {
if (ts.isIdentifier(node.expression)) {
return (node.expression as ts.Identifier).escapedText;
} else if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
return (node.expression as ts.PropertyAccessExpression).name.escapedText;
}

return '';
}

private checkExpression (node: ts.ExpressionWithTypeArguments) {
const name = this.getExpressionName(node);

if (name === 'PureComponent' || name === 'Component') {
const { typeArguments } = node;

if (typeArguments) {
typeArguments.forEach((typeArgument) => {
if (typeArgument.kind === ts.SyntaxKind.UnionType) {
// create a failure at the current position
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), FAILURE_STRING));
}
});
}
}
}
}

export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoPropUnionWalker(sourceFile, this.getOptions()));
}
}
21 changes: 21 additions & 0 deletions src/requirePropAliasRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Lint from 'tslint';
import * as ts from 'typescript';

const FAILURE_STRING = 'Props must alias individual prop types (State, Dispatch, Own, etc)';

// The walker takes care of all the work.
class RequirePropAliasWalker extends Lint.RuleWalker {
public visitImportDeclaration (node: ts.ImportDeclaration) {
// create a failure at the current position
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), FAILURE_STRING));

// call the base version of this visitor to actually parse this node
super.visitImportDeclaration(node);
}
}

export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new RequirePropAliasWalker(sourceFile, this.getOptions()));
}
}
Loading