forked from palantir/tslint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fileNameCasingRule.ts
101 lines (90 loc) · 3.39 KB
/
fileNameCasingRule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* @license
* Copyright 2018 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as path from "path";
import * as ts from "typescript";
import * as Lint from "../index";
import { isCamelCased, isKebabCased, isPascalCased } from "../utils";
enum Casing {
CamelCase = "camel-case",
PascalCase = "pascal-case",
KebabCase = "kebab-case",
}
export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
ruleName: "file-name-casing",
description: "Enforces a consistent file naming convention",
rationale: "Helps maintain a consistent style across a file hierarchy",
optionsDescription: Lint.Utils.dedent`
One of the following arguments must be provided:
* \`${Casing.CamelCase}\`: File names must be camel-cased: \`fileName.ts\`.
* \`${Casing.PascalCase}\`: File names must be Pascal-cased: \`FileName.ts\`.
* \`${Casing.KebabCase}\`: File names must be kebab-cased: \`file-name.ts\`.`,
options: {
type: "array",
items: [
{
type: "string",
enum: [Casing.CamelCase, Casing.PascalCase, Casing.KebabCase],
},
],
},
optionExamples: [
[true, Casing.CamelCase],
[true, Casing.PascalCase],
[true, Casing.KebabCase],
],
hasFix: false,
type: "style",
typescriptOnly: false,
};
/* tslint:enable:object-literal-sort-keys */
private static FAILURE_STRING(expectedCasing: Casing): string {
return `File name must be ${Rule.stylizedNameForCasing(expectedCasing)}`;
}
private static stylizedNameForCasing(casing: Casing): string {
switch (casing) {
case Casing.CamelCase:
return "camelCase";
case Casing.PascalCase:
return "PascalCase";
case Casing.KebabCase:
return "kebab-case";
}
}
private static isCorrectCasing(fileName: string, casing: Casing): boolean {
switch (casing) {
case Casing.CamelCase:
return isCamelCased(fileName);
case Casing.PascalCase:
return isPascalCased(fileName);
case Casing.KebabCase:
return isKebabCased(fileName);
}
}
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
if (this.ruleArguments.length !== 1) {
return [];
}
const casing = this.ruleArguments[0] as Casing;
const fileName = path.parse(sourceFile.fileName).name;
if (!Rule.isCorrectCasing(fileName, casing)) {
return [new Lint.RuleFailure(sourceFile, 0, 0, Rule.FAILURE_STRING(casing), this.ruleName)];
}
return [];
}
}