Skip to content

Commit 664f4a5

Browse files
committed
Initial commit
0 parents  commit 664f4a5

21 files changed

+414
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/node_modules/
2+
/rules/
3+
/npm-debug.*

.npmignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/src/
2+
/test/
3+
/.editorconfig
4+
/.gitignore
5+
/.travis.yml
6+
/tsconfig.json
7+
/tslint.json

.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
language: node_js
2+
node_js:
3+
- "6"
4+
before_deploy:
5+
- npm run build
6+
deploy:
7+
provider: npm
8+
email:
9+
secure: HliUkBM50aFNkVG8j/HKrQNiMbQ9QTlzAB9OE/abuYHv6MPjZmFM46XxuY3YBne+9HrQM2YUse11BroKpT8mbNGw7VoHuEkFtxYg9pQAlVWvGMBusJtdUowHe54VIRjbIaoG4X2yFcW683Bldo2mDx7vYwNwENqEbOx1eEAlbEo0YjGEZiKrg8xTdIUHWFmA+AKnna5g+1DWbLF+bmq0I/swyLjXt/Hqw9NbNR/tFSWnWTY+7fRetaOoKc6OtIVcozZUKMDOupPY/Cx5DKGyf4q9HrZVGg6sE3tXKi8haOJ5uKTR9o9j4Cz0t/MBAd6PNbcM9nyFMfY56OLxbEGPhER0szXlVUKz40RfBs24NAdJYNUOlbZ+49jPzmZWD3ihAlIn/wkGbnFmHAQK7jbur/z9AOksTCmVl6w2o/slyZlmyA77OmMBU2loxPP+RD1hoOJGkHeoM54wrs/ZQQV+MHvReYmHb1GW8/6kncBsyrmAykJJYCWCd5U7WjDkQ+nO3r9qCl40rvPm5MBcvfgOlyZ30qmokHtvZPtBqOuAswpwv0kmuGGHCEWCiXkf3PCa0rTr6iy6qgb1FjOKJBIVRizkTlukIYBP5RwPPMTGLMesRXhL9a+onrz1c7uDv5cVvDLwmUry7Xhrkv0RGANeVEtaNH4xXyVQiOj+7t7Ar8w=
10+
api_key:
11+
secure: jAORKINzH/Q8K96c+kXOCp+qgv6lqdiiDHcbIJyhTaAwEqF+XPPCx1YUspyE2G92Z2fVel0uZv/BFRE1bHnGPSfI+xk+rZMiErGYn1HepWkHUfbPBH+tlzNSMYk7yRT+za/StvO0diUdCByvRqYdcDRorylRUnQugsyAcdkRbzdKoGUHx31Tq1EZjo6DBYRIxwNIAtfUdz+w6yHMmxAwxnfY546vGIfwRXbjfnaizlcPwKM8WmfXfeFPIx6A9cVY5MBBkcYmPSbEGyhfcBLSdPAztNHPNyed4flpMizLkA2+n74+pc+o6WJiDd/6b2WnOVXHEyJe5FQ/xwenFqdrUk/qtQWR1xHLfQUKIihx7cVlAh6LnLeJob/r7NBvRqgWtatW10g2KzFhROegAOKctKm5cSNAyg1HRKzwus31tKlTQhhSLlX8+vVsTrA5Elq5VghR+drmSKrKdyqJCqnBPPfFt/+0DeDNUXGKqVHDnqP5V2GOMJqjsSIDEl52II9+z35W2JeFvLh8y+iZPvpgaHKvD12PJZMHjN8s1VGnqy3N+qgyKGLwwP+shLOekDWffaoTOoJxgUn4ZZVehwljVfclVGs4wWu4v6WFPrFuk8QmtOHxlvLIpGxswEZ4EpKS9kymv4+wMokvSV5b7By2pDn6ap+gWukCw8OORxShVOI=
12+
on:
13+
repo: mcmath/tslint-rules
14+
node: "6"
15+
tags: true

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2017 Akim McMath
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# @mcmath/tslint-rules
2+
3+
[![Version][version-badge]][npm]
4+
[![Build][build-badge]][travis]
5+
6+
Custom rules for TSLint
7+
8+
## Install
9+
10+
Install as an [npm][npm] devDependency. [TypeScript][typescript] and [TSLint][tslint]
11+
should also be installed.
12+
13+
```sh
14+
npm install --save-dev typescript tslint @mcmath/tslint-rules
15+
```
16+
17+
## Usage
18+
19+
Include a `tslint.json` file in your project and add `"@mcmath/tslint-rules"` to
20+
the `"extends"` field. Custom rules can then be enabled under `"rules"`.
21+
22+
```json
23+
{
24+
"extends": ["@mcmath/tslint-rules"],
25+
"rules": {
26+
"enum-member-name": [true, "caps-case"]
27+
}
28+
}
29+
```
30+
31+
## Rules
32+
33+
#### enum-member-name
34+
35+
Ensures `enum` members follow a consistent naming convention.
36+
37+
This rule accepts a single string option. If no option is given,
38+
"pascal-case" is assumed.
39+
40+
| Option | Attributes | Example |
41+
|:--------------|:-----------|:------------|
42+
| "pascal-case" | default | PascalCase |
43+
| "camel-case" | | camelCase |
44+
| "caps-case" | | CAPS_CASE |
45+
| "snake-case" | | snake_case |
46+
47+
## License
48+
49+
Copyright © 2017 Akim McMath. Licensed under the [MIT License][license].
50+
51+
[version-badge]: https://img.shields.io/npm/v/@mcmath/tslint-rules.svg?style=flat-square
52+
[build-badge]: https://img.shields.io/travis/mcmath/tslint-rules/master.svg?style=flat-square
53+
[npm]: https://www.npmjs.com/package/@mcmath/tslint-rules
54+
[travis]: https://travis-ci.org/mcmath/tslint-rules
55+
[typescript]: https://www.typescriptlang.org/
56+
[tslint]: https://palantir.github.io/tslint/
57+
[license]: LICENSE

index.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rulesDirectory": ["./rules"]
3+
}

package.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "@mcmath/tslint-rules",
3+
"version": "0.0.0",
4+
"description": "Custom rules for TSLint",
5+
"main": "index.json",
6+
"keywords": [
7+
"tslint",
8+
"tslint-rules",
9+
"linter",
10+
"typescript"
11+
],
12+
"scripts": {
13+
"build": "rimraf rules && tsc",
14+
"test": "rimraf rules && tsc && tslint src && tslint -r rules --test \"test/rules/*/*\" && jsonlint index.json -q"
15+
},
16+
"engines": {
17+
"node": ">=4.0"
18+
},
19+
"publishConfig": {
20+
"access": "public"
21+
},
22+
"author": "Akim McMath <[email protected]>",
23+
"license": "MIT",
24+
"repository": {
25+
"type": "git",
26+
"url": "git+https://github.com/mcmath/tslint-rules.git"
27+
},
28+
"bugs": {
29+
"url": "https://github.com/mcmath/tslint-rules/issues"
30+
},
31+
"homepage": "https://github.com/mcmath/tslint-rules#readme",
32+
"peerDependencies": {
33+
"typescript": "2",
34+
"tslint": "5"
35+
},
36+
"dependencies": {
37+
"tslib": "^1.6.0"
38+
},
39+
"devDependencies": {
40+
"@mcmath/tslint-config": "^1.0.2",
41+
"jsonlint": "^1.6.2",
42+
"rimraf": "^2.6.1",
43+
"tslint": "^5.1.0",
44+
"typescript": "^2.2.2"
45+
}
46+
}

src/enumMemberNameRule.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { EnumDeclaration, EnumMember, SourceFile } from "typescript";
2+
import { Rules, RuleWalker, RuleFailure } from "tslint";
3+
import { ENUM_MEMBER_NAME_OPTIONS } from "./enumMemberNameSchema";
4+
5+
export class Rule extends Rules.AbstractRule {
6+
7+
public apply(sourceFile: SourceFile): RuleFailure[] {
8+
return this.applyWithWalker(new EnumMembersWalker(sourceFile, this.getOptions()));
9+
}
10+
11+
}
12+
13+
class EnumMembersWalker extends RuleWalker {
14+
15+
public visitEnumDeclaration(node: EnumDeclaration): void {
16+
node.members.forEach(this.validateEnumMember, this);
17+
super.visitEnumDeclaration(node);
18+
}
19+
20+
private validateEnumMember(node: EnumMember): void {
21+
this.validateEnumMemberName(node, node.name.getText());
22+
}
23+
24+
private validateEnumMemberName(node: EnumMember, name: string): void {
25+
for (const { option, description, validate } of ENUM_MEMBER_NAME_OPTIONS) {
26+
if (this.hasOption(option)) {
27+
if (!validate(name)) this.registerFailure(node, description);
28+
return;
29+
}
30+
}
31+
if (!ENUM_MEMBER_NAME_OPTIONS[0].validate(name)) {
32+
this.registerFailure(node, ENUM_MEMBER_NAME_OPTIONS[0].description);
33+
}
34+
}
35+
36+
private registerFailure(node: EnumMember, description: string): void {
37+
this.addFailureAtNode(node, `Enum members must be in ${description}`);
38+
}
39+
40+
}

src/enumMemberNameSchema.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export interface EnumMemberNameOption {
2+
option: string;
3+
description: string;
4+
validate: (str: string) => boolean;
5+
}
6+
7+
/**
8+
* A list of option definitions. The first option is the default option.
9+
*/
10+
export const ENUM_MEMBER_NAME_OPTIONS: EnumMemberNameOption[] = [
11+
{
12+
option: "pascal-case",
13+
description: "PascalCase",
14+
validate: (str: string) => /^[A-Z][0-9A-Za-z]*$/.test(str) && (str.length === 1 || /[a-z]/.test(str))
15+
},
16+
{
17+
option: "camel-case",
18+
description: "camelCase",
19+
validate: (str: string) => /^[a-z][0-9A-Za-z]*$/.test(str)
20+
},
21+
{
22+
option: "caps-case",
23+
description: "CAPS_CASE",
24+
validate: (str: string) => /^[A-Z][0-9A-Z_]*[0-9A-Z]$|^[A-Z]$/.test(str)
25+
},
26+
{
27+
option: "snake-case",
28+
description: "snake_case",
29+
validate: (str: string) => /^[a-z][0-9a-z_]*[0-9a-z]$|^[a-z]$/.test(str)
30+
}
31+
];
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
enum LetterCase {
2+
PascalCase,
3+
~~~~~~~~~~ [Enum members must be in camelCase]
4+
PASCALCase,
5+
~~~~~~~~~~ [Enum members must be in camelCase]
6+
camelCase,
7+
camelcase,
8+
CAPS_CASE,
9+
~~~~~~~~~ [Enum members must be in camelCase]
10+
CAPSCASE,
11+
~~~~~~~~ [Enum members must be in camelCase]
12+
_BAD_CAPS_CASE,
13+
~~~~~~~~~~~~~~ [Enum members must be in camelCase]
14+
BAD_CAPS_CASE_,
15+
~~~~~~~~~~~~~~ [Enum members must be in camelCase]
16+
snake_case,
17+
~~~~~~~~~~ [Enum members must be in camelCase]
18+
snakecase,
19+
_bad_snake_case,
20+
~~~~~~~~~~~~~~~ [Enum members must be in camelCase]
21+
bad_snake_case_,
22+
~~~~~~~~~~~~~~~ [Enum members must be in camelCase]
23+
X,
24+
~ [Enum members must be in camelCase]
25+
x
26+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"enum-member-name": [true, "camel-case"]
4+
}
5+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
enum LetterCase {
2+
PascalCase,
3+
~~~~~~~~~~ [Enum members must be in CAPS_CASE]
4+
PASCALCase,
5+
~~~~~~~~~~ [Enum members must be in CAPS_CASE]
6+
camelCase,
7+
~~~~~~~~~ [Enum members must be in CAPS_CASE]
8+
camelcase,
9+
~~~~~~~~~ [Enum members must be in CAPS_CASE]
10+
CAPS_CASE,
11+
CAPSCASE,
12+
_BAD_CAPS_CASE,
13+
~~~~~~~~~~~~~~ [Enum members must be in CAPS_CASE]
14+
BAD_CAPS_CASE_,
15+
~~~~~~~~~~~~~~ [Enum members must be in CAPS_CASE]
16+
snake_case,
17+
~~~~~~~~~~ [Enum members must be in CAPS_CASE]
18+
snakecase,
19+
~~~~~~~~~ [Enum members must be in CAPS_CASE]
20+
_bad_snake_case,
21+
~~~~~~~~~~~~~~~ [Enum members must be in CAPS_CASE]
22+
bad_snake_case_,
23+
~~~~~~~~~~~~~~~ [Enum members must be in CAPS_CASE]
24+
X,
25+
x
26+
~ [Enum members must be in CAPS_CASE]
27+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"enum-member-name": [true, "caps-case"]
4+
}
5+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
enum LetterCase {
2+
PascalCase,
3+
PASCALCase,
4+
camelCase,
5+
~~~~~~~~~ [Enum members must be in PascalCase]
6+
camelcase,
7+
~~~~~~~~~ [Enum members must be in PascalCase]
8+
CAPS_CASE,
9+
~~~~~~~~~ [Enum members must be in PascalCase]
10+
CAPSCASE,
11+
~~~~~~~~ [Enum members must be in PascalCase]
12+
_BAD_CAPS_CASE,
13+
~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
14+
BAD_CAPS_CASE_,
15+
~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
16+
snake_case,
17+
~~~~~~~~~~ [Enum members must be in PascalCase]
18+
snakecase,
19+
~~~~~~~~~ [Enum members must be in PascalCase]
20+
_bad_snake_case,
21+
~~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
22+
bad_snake_case_,
23+
~~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
24+
X,
25+
x
26+
~ [Enum members must be in PascalCase]
27+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"enum-member-name": true
4+
}
5+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
enum LetterCase {
2+
PascalCase,
3+
PASCALCase,
4+
camelCase,
5+
~~~~~~~~~ [Enum members must be in PascalCase]
6+
camelcase,
7+
~~~~~~~~~ [Enum members must be in PascalCase]
8+
CAPS_CASE,
9+
~~~~~~~~~ [Enum members must be in PascalCase]
10+
CAPSCASE,
11+
~~~~~~~~ [Enum members must be in PascalCase]
12+
_BAD_CAPS_CASE,
13+
~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
14+
BAD_CAPS_CASE_,
15+
~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
16+
snake_case,
17+
~~~~~~~~~~ [Enum members must be in PascalCase]
18+
snakecase,
19+
~~~~~~~~~ [Enum members must be in PascalCase]
20+
_bad_snake_case,
21+
~~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
22+
bad_snake_case_,
23+
~~~~~~~~~~~~~~~ [Enum members must be in PascalCase]
24+
X,
25+
x
26+
~ [Enum members must be in PascalCase]
27+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"enum-member-name": [true, "pascal-case"]
4+
}
5+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
enum LetterCase {
2+
PascalCase,
3+
~~~~~~~~~~ [Enum members must be in snake_case]
4+
PASCALCase,
5+
~~~~~~~~~~ [Enum members must be in snake_case]
6+
camelCase,
7+
~~~~~~~~~ [Enum members must be in snake_case]
8+
camelcase,
9+
CAPS_CASE,
10+
~~~~~~~~~ [Enum members must be in snake_case]
11+
CAPSCASE,
12+
~~~~~~~~ [Enum members must be in snake_case]
13+
_BAD_CAPS_CASE,
14+
~~~~~~~~~~~~~~ [Enum members must be in snake_case]
15+
BAD_CAPS_CASE_,
16+
~~~~~~~~~~~~~~ [Enum members must be in snake_case]
17+
snake_case,
18+
snakecase,
19+
_bad_snake_case,
20+
~~~~~~~~~~~~~~~ [Enum members must be in snake_case]
21+
bad_snake_case_,
22+
~~~~~~~~~~~~~~~ [Enum members must be in snake_case]
23+
X,
24+
~ [Enum members must be in snake_case]
25+
x
26+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"enum-member-name": [true, "snake-case"]
4+
}
5+
}

0 commit comments

Comments
 (0)