@dvukovic/style-guide 0.3.108 → 0.3.109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { noCommentedOutCode } from "../rules/no-commented-out-code/no-commented-out-code.js"
|
|
2
|
+
import { noT } from "../rules/no-t/no-t.js"
|
|
2
3
|
|
|
3
4
|
/** @type {import("@eslint/config-helpers").Config} */
|
|
4
5
|
export const dvukovic = {
|
|
@@ -6,10 +7,12 @@ export const dvukovic = {
|
|
|
6
7
|
dvukovic: {
|
|
7
8
|
rules: {
|
|
8
9
|
"no-commented-out-code": noCommentedOutCode,
|
|
10
|
+
"no-t": noT,
|
|
9
11
|
},
|
|
10
12
|
},
|
|
11
13
|
},
|
|
12
14
|
rules: {
|
|
13
15
|
"dvukovic/no-commented-out-code": "error",
|
|
16
|
+
"dvukovic/no-t": "error",
|
|
14
17
|
},
|
|
15
18
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const noT = {
|
|
2
|
+
create(context) {
|
|
3
|
+
const [{ prefix = "" } = {}] = context.options
|
|
4
|
+
|
|
5
|
+
return {
|
|
6
|
+
"TSTypeParameter > Identifier[name=/^.$/]"(node) {
|
|
7
|
+
context.report({
|
|
8
|
+
data: { name: node.name },
|
|
9
|
+
messageId: "forbidden",
|
|
10
|
+
node,
|
|
11
|
+
})
|
|
12
|
+
},
|
|
13
|
+
"TSTypeParameter > Identifier[name=/^.{2,}$/]"(node) {
|
|
14
|
+
if (prefix && !node.name.startsWith(prefix)) {
|
|
15
|
+
context.report({
|
|
16
|
+
data: { name: node.name, prefix },
|
|
17
|
+
messageId: "prefix",
|
|
18
|
+
node,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
meta: {
|
|
25
|
+
docs: {
|
|
26
|
+
description: "Forbids single-character type parameters.",
|
|
27
|
+
},
|
|
28
|
+
messages: {
|
|
29
|
+
forbidden: `Single-character type parameters are forbidden. Choose a more descriptive name for "{{name}}"`,
|
|
30
|
+
prefix: `Type parameter "{{name}}" does not have prefix "{{prefix}}"`,
|
|
31
|
+
},
|
|
32
|
+
schema: [
|
|
33
|
+
{
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
properties: {
|
|
36
|
+
prefix: { type: "string" },
|
|
37
|
+
},
|
|
38
|
+
type: "object",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
type: "problem",
|
|
42
|
+
},
|
|
43
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ESLint } from "eslint"
|
|
2
|
+
import tseslint from "typescript-eslint"
|
|
3
|
+
|
|
4
|
+
import { dvukovic } from "../../plugins/dvukovic.js"
|
|
5
|
+
|
|
6
|
+
const eslint = new ESLint({
|
|
7
|
+
overrideConfig: [
|
|
8
|
+
{
|
|
9
|
+
files: ["**/*.ts"],
|
|
10
|
+
languageOptions: {
|
|
11
|
+
parser: tseslint.parser,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
dvukovic,
|
|
15
|
+
],
|
|
16
|
+
overrideConfigFile: true,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe("dvukovic/no-t", () => {
|
|
20
|
+
test("detects single-character type parameter", async () => {
|
|
21
|
+
const code = `function foo<T>(arg: T): T { return arg }\n`
|
|
22
|
+
|
|
23
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
24
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
25
|
+
return message.ruleId === "dvukovic/no-t"
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
expect(errors?.length).toBe(1)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test("detects multiple single-character type parameters", async () => {
|
|
32
|
+
const code = `type Entry<K, V> = { key: K; value: V }\n`
|
|
33
|
+
|
|
34
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
35
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
36
|
+
return message.ruleId === "dvukovic/no-t"
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
expect(errors?.length).toBe(2)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test("allows descriptive type parameters", async () => {
|
|
43
|
+
const code = `function foo<Element>(arg: Element): Element { return arg }\n`
|
|
44
|
+
|
|
45
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
46
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
47
|
+
return message.ruleId === "dvukovic/no-t"
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
expect(errors?.length).toBe(0)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test("allows descriptive type parameters in type alias", async () => {
|
|
54
|
+
const code = `type Entry<Key, Value> = { key: Key; value: Value }\n`
|
|
55
|
+
|
|
56
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
57
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
58
|
+
return message.ruleId === "dvukovic/no-t"
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
expect(errors?.length).toBe(0)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test("detects single-character in interface", async () => {
|
|
65
|
+
const code = `interface Container<T> { value: T }\n`
|
|
66
|
+
|
|
67
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
68
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
69
|
+
return message.ruleId === "dvukovic/no-t"
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
expect(errors?.length).toBe(1)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test("detects single-character in class", async () => {
|
|
76
|
+
const code = `class Box<T> { constructor(public value: T) {} }\n`
|
|
77
|
+
|
|
78
|
+
const results = await eslint.lintText(code, { filePath: "test.ts" })
|
|
79
|
+
const errors = results[0]?.messages.filter((message) => {
|
|
80
|
+
return message.ruleId === "dvukovic/no-t"
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(errors?.length).toBe(1)
|
|
84
|
+
})
|
|
85
|
+
})
|