@apptoolkit/harness 0.0.0-stage → 1.0.0
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/README.md +57 -2
- package/dist/apptoolkit-harness-1.0.0.tgz +0 -0
- package/dist/bun/apptoolkit-harness-1.0.0.tgz +0 -0
- package/dist/bun/native/LICENSE +21 -0
- package/dist/bun/native/README.md +33 -0
- package/dist/bun/native/harness +4 -0
- package/dist/bun/native/payload/HARNESS.md +21 -0
- package/dist/bun/native/payload/author-style/README.md +56 -0
- package/dist/bun/native/payload/author-style/biome-core.json +57 -0
- package/dist/bun/native/payload/author-style/biome-react.json +9 -0
- package/dist/bun/native/payload/author-style/biome-sql.json +9 -0
- package/dist/bun/native/payload/author-style/bun.lock +37 -0
- package/dist/bun/native/payload/author-style/check.llm.md +17 -0
- package/dist/bun/native/payload/author-style/check.test.llm.md +17 -0
- package/dist/bun/native/payload/author-style/check.test.ts +238 -0
- package/dist/bun/native/payload/author-style/check.ts +181 -0
- package/dist/bun/native/payload/author-style/member-spacing.test.ts +172 -0
- package/dist/bun/native/payload/author-style/member-spacing.ts +106 -0
- package/dist/bun/native/payload/author-style/package.json +18 -0
- package/dist/bun/native/payload/author-style/plugins/class-member-order.grit +133 -0
- package/dist/bun/native/payload/author-style/plugins/event-handler-names.grit +110 -0
- package/dist/bun/native/payload/author-style/plugins/explicit-arrow-body.grit +15 -0
- package/dist/bun/native/payload/author-style/plugins/explicit-source-constructs.grit +10 -0
- package/dist/bun/native/payload/author-style/plugins/react-arrow-body.grit +85 -0
- package/dist/bun/native/payload/author-style/plugins/sql-style.grit +125 -0
- package/dist/bun/native/payload/author-style/react-module.llm.md +17 -0
- package/dist/bun/native/payload/author-style/react-module.test.ts +150 -0
- package/dist/bun/native/payload/author-style/react-module.ts +255 -0
- package/dist/bun/native/payload/author-style/source-policy.llm.md +17 -0
- package/dist/bun/native/payload/author-style/source-policy.test.ts +70 -0
- package/dist/bun/native/payload/author-style/source-policy.ts +215 -0
- package/dist/bun/native/payload/author-style/spacing.llm.md +17 -0
- package/dist/bun/native/payload/author-style/spacing.test.ts +174 -0
- package/dist/bun/native/payload/author-style/spacing.ts +211 -0
- package/dist/bun/native/payload/harness/POLICY.md +33 -0
- package/dist/bun/native/payload/harness/PROJECT.md +26 -0
- package/dist/bun/native/payload/harness/REVIEW.md +17 -0
- package/dist/bun/native/payload/harness/TEMPLATES.md +20 -0
- package/dist/bun/native/payload/harness/WORKFLOWS.md +65 -0
- package/dist/bun/native/payload/harness/runtime/ZOD-LICENSE +21 -0
- package/dist/bun/native/payload/harness/runtime/harness.mjs +104 -0
- package/dist/bun/native/payload/harness/services/README.md +26 -0
- package/dist/bun/native/payload/harness/services/penpot.json +7 -0
- package/dist/bun/native/payload/harness/services/plane.json +9 -0
- package/dist/bun/native/payload/harness/workflows/W01.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W02.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W03.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W04.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W05.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W06.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W07.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W08.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W09.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W10.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W11.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W12.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W13.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W14.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W15.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W16.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W17.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W18.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W19.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W20.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W21.md +15 -0
- package/dist/bun/native/payload/harness/workflows/W22.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W23.md +21 -0
- package/dist/bun/native/payload/harness/workflows/W24.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W25.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W26.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W27.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W28.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W29.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W30.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W31.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W32.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W33.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W34.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W35.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W36.md +13 -0
- package/dist/bun/native/payload/harness/workflows/W37.md +13 -0
- package/dist/bun/npm/LICENSE +21 -0
- package/dist/bun/npm/README.md +33 -0
- package/dist/bun/npm/harness.js +104 -0
- package/dist/bun/npm/package.json +23 -0
- package/dist/bun/npm/payload/HARNESS.md +21 -0
- package/dist/bun/npm/payload/author-style/README.md +56 -0
- package/dist/bun/npm/payload/author-style/biome-core.json +57 -0
- package/dist/bun/npm/payload/author-style/biome-react.json +9 -0
- package/dist/bun/npm/payload/author-style/biome-sql.json +9 -0
- package/dist/bun/npm/payload/author-style/bun.lock +37 -0
- package/dist/bun/npm/payload/author-style/check.llm.md +17 -0
- package/dist/bun/npm/payload/author-style/check.test.llm.md +17 -0
- package/dist/bun/npm/payload/author-style/check.test.ts +238 -0
- package/dist/bun/npm/payload/author-style/check.ts +181 -0
- package/dist/bun/npm/payload/author-style/member-spacing.test.ts +172 -0
- package/dist/bun/npm/payload/author-style/member-spacing.ts +106 -0
- package/dist/bun/npm/payload/author-style/package.json +18 -0
- package/dist/bun/npm/payload/author-style/plugins/class-member-order.grit +133 -0
- package/dist/bun/npm/payload/author-style/plugins/event-handler-names.grit +110 -0
- package/dist/bun/npm/payload/author-style/plugins/explicit-arrow-body.grit +15 -0
- package/dist/bun/npm/payload/author-style/plugins/explicit-source-constructs.grit +10 -0
- package/dist/bun/npm/payload/author-style/plugins/react-arrow-body.grit +85 -0
- package/dist/bun/npm/payload/author-style/plugins/sql-style.grit +125 -0
- package/dist/bun/npm/payload/author-style/react-module.llm.md +17 -0
- package/dist/bun/npm/payload/author-style/react-module.test.ts +150 -0
- package/dist/bun/npm/payload/author-style/react-module.ts +255 -0
- package/dist/bun/npm/payload/author-style/source-policy.llm.md +17 -0
- package/dist/bun/npm/payload/author-style/source-policy.test.ts +70 -0
- package/dist/bun/npm/payload/author-style/source-policy.ts +215 -0
- package/dist/bun/npm/payload/author-style/spacing.llm.md +17 -0
- package/dist/bun/npm/payload/author-style/spacing.test.ts +174 -0
- package/dist/bun/npm/payload/author-style/spacing.ts +211 -0
- package/dist/bun/npm/payload/harness/POLICY.md +33 -0
- package/dist/bun/npm/payload/harness/PROJECT.md +26 -0
- package/dist/bun/npm/payload/harness/REVIEW.md +17 -0
- package/dist/bun/npm/payload/harness/TEMPLATES.md +20 -0
- package/dist/bun/npm/payload/harness/WORKFLOWS.md +65 -0
- package/dist/bun/npm/payload/harness/runtime/ZOD-LICENSE +21 -0
- package/dist/bun/npm/payload/harness/runtime/harness.mjs +104 -0
- package/dist/bun/npm/payload/harness/services/README.md +26 -0
- package/dist/bun/npm/payload/harness/services/penpot.json +7 -0
- package/dist/bun/npm/payload/harness/services/plane.json +9 -0
- package/dist/bun/npm/payload/harness/workflows/W01.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W02.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W03.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W04.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W05.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W06.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W07.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W08.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W09.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W10.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W11.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W12.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W13.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W14.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W15.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W16.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W17.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W18.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W19.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W20.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W21.md +15 -0
- package/dist/bun/npm/payload/harness/workflows/W22.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W23.md +21 -0
- package/dist/bun/npm/payload/harness/workflows/W24.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W25.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W26.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W27.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W28.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W29.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W30.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W31.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W32.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W33.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W34.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W35.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W36.md +13 -0
- package/dist/bun/npm/payload/harness/workflows/W37.md +13 -0
- package/dist/npm/LICENSE +21 -0
- package/dist/npm/README.md +30 -0
- package/dist/npm/harness.js +104 -0
- package/dist/npm/package.json +25 -0
- package/dist/npm/payload/HARNESS.md +21 -0
- package/dist/npm/payload/author-style/README.md +56 -0
- package/dist/npm/payload/author-style/biome-core.json +57 -0
- package/dist/npm/payload/author-style/biome-react.json +9 -0
- package/dist/npm/payload/author-style/biome-sql.json +9 -0
- package/dist/npm/payload/author-style/check.llm.md +17 -0
- package/dist/npm/payload/author-style/check.test.llm.md +17 -0
- package/dist/npm/payload/author-style/check.test.ts +224 -0
- package/dist/npm/payload/author-style/check.ts +179 -0
- package/dist/npm/payload/author-style/member-spacing.test.ts +172 -0
- package/dist/npm/payload/author-style/member-spacing.ts +106 -0
- package/dist/npm/payload/author-style/package-lock.json +180 -0
- package/dist/npm/payload/author-style/package.json +17 -0
- package/dist/npm/payload/author-style/plugins/class-member-order.grit +133 -0
- package/dist/npm/payload/author-style/plugins/event-handler-names.grit +110 -0
- package/dist/npm/payload/author-style/plugins/explicit-arrow-body.grit +15 -0
- package/dist/npm/payload/author-style/plugins/explicit-source-constructs.grit +10 -0
- package/dist/npm/payload/author-style/plugins/react-arrow-body.grit +85 -0
- package/dist/npm/payload/author-style/plugins/sql-style.grit +125 -0
- package/dist/npm/payload/author-style/react-module.llm.md +17 -0
- package/dist/npm/payload/author-style/react-module.test.ts +150 -0
- package/dist/npm/payload/author-style/react-module.ts +255 -0
- package/dist/npm/payload/author-style/source-policy.llm.md +17 -0
- package/dist/npm/payload/author-style/source-policy.test.ts +70 -0
- package/dist/npm/payload/author-style/source-policy.ts +215 -0
- package/dist/npm/payload/author-style/spacing.llm.md +17 -0
- package/dist/npm/payload/author-style/spacing.test.ts +174 -0
- package/dist/npm/payload/author-style/spacing.ts +211 -0
- package/dist/npm/payload/harness/POLICY.md +33 -0
- package/dist/npm/payload/harness/PROJECT.md +26 -0
- package/dist/npm/payload/harness/REVIEW.md +17 -0
- package/dist/npm/payload/harness/TEMPLATES.md +20 -0
- package/dist/npm/payload/harness/WORKFLOWS.md +65 -0
- package/dist/npm/payload/harness/runtime/ZOD-LICENSE +21 -0
- package/dist/npm/payload/harness/runtime/harness.mjs +104 -0
- package/dist/npm/payload/harness/services/README.md +26 -0
- package/dist/npm/payload/harness/services/penpot.json +7 -0
- package/dist/npm/payload/harness/services/plane.json +9 -0
- package/dist/npm/payload/harness/workflows/W01.md +13 -0
- package/dist/npm/payload/harness/workflows/W02.md +13 -0
- package/dist/npm/payload/harness/workflows/W03.md +13 -0
- package/dist/npm/payload/harness/workflows/W04.md +13 -0
- package/dist/npm/payload/harness/workflows/W05.md +13 -0
- package/dist/npm/payload/harness/workflows/W06.md +13 -0
- package/dist/npm/payload/harness/workflows/W07.md +13 -0
- package/dist/npm/payload/harness/workflows/W08.md +13 -0
- package/dist/npm/payload/harness/workflows/W09.md +13 -0
- package/dist/npm/payload/harness/workflows/W10.md +13 -0
- package/dist/npm/payload/harness/workflows/W11.md +13 -0
- package/dist/npm/payload/harness/workflows/W12.md +13 -0
- package/dist/npm/payload/harness/workflows/W13.md +13 -0
- package/dist/npm/payload/harness/workflows/W14.md +13 -0
- package/dist/npm/payload/harness/workflows/W15.md +13 -0
- package/dist/npm/payload/harness/workflows/W16.md +13 -0
- package/dist/npm/payload/harness/workflows/W17.md +13 -0
- package/dist/npm/payload/harness/workflows/W18.md +13 -0
- package/dist/npm/payload/harness/workflows/W19.md +13 -0
- package/dist/npm/payload/harness/workflows/W20.md +13 -0
- package/dist/npm/payload/harness/workflows/W21.md +15 -0
- package/dist/npm/payload/harness/workflows/W22.md +13 -0
- package/dist/npm/payload/harness/workflows/W23.md +21 -0
- package/dist/npm/payload/harness/workflows/W24.md +13 -0
- package/dist/npm/payload/harness/workflows/W25.md +13 -0
- package/dist/npm/payload/harness/workflows/W26.md +13 -0
- package/dist/npm/payload/harness/workflows/W27.md +13 -0
- package/dist/npm/payload/harness/workflows/W28.md +13 -0
- package/dist/npm/payload/harness/workflows/W29.md +13 -0
- package/dist/npm/payload/harness/workflows/W30.md +13 -0
- package/dist/npm/payload/harness/workflows/W31.md +13 -0
- package/dist/npm/payload/harness/workflows/W32.md +13 -0
- package/dist/npm/payload/harness/workflows/W33.md +13 -0
- package/dist/npm/payload/harness/workflows/W34.md +13 -0
- package/dist/npm/payload/harness/workflows/W35.md +13 -0
- package/dist/npm/payload/harness/workflows/W36.md +13 -0
- package/dist/npm/payload/harness/workflows/W37.md +13 -0
- package/package.json +35 -4
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { findMemberSpacingIssues } from './member-spacing.ts';
|
|
5
|
+
|
|
6
|
+
const memberMessage = 'Leave one blank line between class members.';
|
|
7
|
+
const overloadMessage = 'Keep adjacent signatures and the implementation of an overload together.';
|
|
8
|
+
|
|
9
|
+
function check(lines: readonly string[]) {
|
|
10
|
+
return findMemberSpacingIssues(lines.join('\n'), 'example.ts');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test('requires one blank line between authored properties, methods and accessors', () => {
|
|
14
|
+
assert.deepEqual(
|
|
15
|
+
check([
|
|
16
|
+
'class Example {',
|
|
17
|
+
' public value = 1;',
|
|
18
|
+
' public other = 2;',
|
|
19
|
+
'',
|
|
20
|
+
'',
|
|
21
|
+
' public get label() { return this.value; }',
|
|
22
|
+
'',
|
|
23
|
+
' public set label(value: number) { this.value = value; }',
|
|
24
|
+
'}',
|
|
25
|
+
]),
|
|
26
|
+
[
|
|
27
|
+
{ line: 3, column: 3, message: memberMessage },
|
|
28
|
+
{ line: 6, column: 3, message: memberMessage },
|
|
29
|
+
],
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('groups same-name overloads and constructor overloads with their implementations', () => {
|
|
34
|
+
assert.deepEqual(
|
|
35
|
+
check([
|
|
36
|
+
'class Example {',
|
|
37
|
+
' public constructor(value: string);',
|
|
38
|
+
' public constructor(value: number);',
|
|
39
|
+
' public constructor(public value: string | number) {}',
|
|
40
|
+
'',
|
|
41
|
+
' public lookup(value: string): string;',
|
|
42
|
+
" public 'lookup'(value: number): number;",
|
|
43
|
+
" public ['lookup'](value: string | number): string | number { return value; }",
|
|
44
|
+
'',
|
|
45
|
+
' public static lookup(value: string): string;',
|
|
46
|
+
' public static lookup(value: number): number;',
|
|
47
|
+
' public static lookup(value: string | number): string | number { return value; }',
|
|
48
|
+
'}',
|
|
49
|
+
]),
|
|
50
|
+
[],
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('reports breaks within overloads and separates distinct overload groups', () => {
|
|
55
|
+
assert.deepEqual(
|
|
56
|
+
check([
|
|
57
|
+
'class Example {',
|
|
58
|
+
' public constructor(value: string);',
|
|
59
|
+
'',
|
|
60
|
+
' public constructor(public value: string) {}',
|
|
61
|
+
' public lookup(value: string): string;',
|
|
62
|
+
'',
|
|
63
|
+
' public lookup(value: number): number;',
|
|
64
|
+
' public lookup(value: string | number): string | number { return value; }',
|
|
65
|
+
'',
|
|
66
|
+
' public static lookup(value: string): string;',
|
|
67
|
+
'',
|
|
68
|
+
' public static lookup(value: string): string { return value; }',
|
|
69
|
+
'}',
|
|
70
|
+
]),
|
|
71
|
+
[
|
|
72
|
+
{ line: 4, column: 3, message: overloadMessage },
|
|
73
|
+
{ line: 5, column: 3, message: memberMessage },
|
|
74
|
+
{ line: 7, column: 3, message: overloadMessage },
|
|
75
|
+
{ line: 12, column: 3, message: overloadMessage },
|
|
76
|
+
],
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('keeps bodyless members separate if a matching adjacent member is absent', () => {
|
|
81
|
+
assert.deepEqual(
|
|
82
|
+
check([
|
|
83
|
+
'abstract class Example {',
|
|
84
|
+
' public abstract read(value: string): string;',
|
|
85
|
+
' public static read(value: string): string { return value; }',
|
|
86
|
+
' public abstract write(value: string): void;',
|
|
87
|
+
' public value = 1;',
|
|
88
|
+
'',
|
|
89
|
+
' public writeOther(): void {}',
|
|
90
|
+
'}',
|
|
91
|
+
]),
|
|
92
|
+
[
|
|
93
|
+
{ line: 3, column: 3, message: memberMessage },
|
|
94
|
+
{ line: 4, column: 3, message: memberMessage },
|
|
95
|
+
{ line: 5, column: 3, message: memberMessage },
|
|
96
|
+
],
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('groups overload declarations in ambient and abstract classes without requiring a body', () => {
|
|
101
|
+
assert.deepEqual(
|
|
102
|
+
check([
|
|
103
|
+
'declare class Ambient {',
|
|
104
|
+
' public lookup(value: string): string;',
|
|
105
|
+
' public lookup(value: number): number;',
|
|
106
|
+
'}',
|
|
107
|
+
'abstract class Example {',
|
|
108
|
+
' public abstract lookup(value: string): string;',
|
|
109
|
+
'',
|
|
110
|
+
' public abstract lookup(value: number): number;',
|
|
111
|
+
'}',
|
|
112
|
+
]),
|
|
113
|
+
[{ line: 8, column: 3, message: overloadMessage }],
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('matches overloads with the same computed or private name', () => {
|
|
118
|
+
assert.deepEqual(
|
|
119
|
+
check([
|
|
120
|
+
'class Example {',
|
|
121
|
+
' public [Symbol.iterator](value: string): string;',
|
|
122
|
+
' public [Symbol.iterator](value: string): string { return value; }',
|
|
123
|
+
'',
|
|
124
|
+
' #lookup(value: string): string;',
|
|
125
|
+
' #lookup(value: string): string { return value; }',
|
|
126
|
+
'}',
|
|
127
|
+
]),
|
|
128
|
+
[],
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('counts spacing outside comments and preserves comment ownership with CRLF', () => {
|
|
133
|
+
const source = [
|
|
134
|
+
'class Example {',
|
|
135
|
+
' public value = 1; /* trailing',
|
|
136
|
+
'',
|
|
137
|
+
' details */',
|
|
138
|
+
' /* leading',
|
|
139
|
+
'',
|
|
140
|
+
' details */',
|
|
141
|
+
' public next = 2;',
|
|
142
|
+
'',
|
|
143
|
+
' // Attached to the following member.',
|
|
144
|
+
' public final = 3;',
|
|
145
|
+
'}',
|
|
146
|
+
].join('\r\n');
|
|
147
|
+
|
|
148
|
+
assert.deepEqual(findMemberSpacingIssues(source, 'example.ts'), [{ line: 8, column: 3, message: memberMessage }]);
|
|
149
|
+
assert.deepEqual(findMemberSpacingIssues(source.replace('*/\r\n /*', '*/\r\n \t\r\n /*'), 'example.ts'), []);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('visits class expressions and nested classes in source order and ignores non-class members', () => {
|
|
153
|
+
const source = [
|
|
154
|
+
'interface Shape { x: number; y: number }',
|
|
155
|
+
'const shape = { x: 1, y: 2 };',
|
|
156
|
+
'const Example = class {',
|
|
157
|
+
' public nested = class {',
|
|
158
|
+
' public first = 1;',
|
|
159
|
+
' public second = 2;',
|
|
160
|
+
' };',
|
|
161
|
+
' static { run(); }',
|
|
162
|
+
'}',
|
|
163
|
+
'class Empty { ; }',
|
|
164
|
+
'class Single { public value = 1; }',
|
|
165
|
+
'export const view = <button>Save</button>;',
|
|
166
|
+
].join('\n');
|
|
167
|
+
|
|
168
|
+
assert.deepEqual(findMemberSpacingIssues(source, 'example.tsx'), [
|
|
169
|
+
{ line: 6, column: 5, message: memberMessage },
|
|
170
|
+
{ line: 8, column: 3, message: memberMessage },
|
|
171
|
+
]);
|
|
172
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
type MemberSpacingIssue = { line: number; column: number; message: string };
|
|
4
|
+
type OverloadMember = ts.ConstructorDeclaration | ts.MethodDeclaration;
|
|
5
|
+
|
|
6
|
+
function isOverloadMember(member: ts.ClassElement): member is OverloadMember {
|
|
7
|
+
return ts.isConstructorDeclaration(member) || ts.isMethodDeclaration(member);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function methodName(member: ts.MethodDeclaration, file: ts.SourceFile): string {
|
|
11
|
+
const name = member.name;
|
|
12
|
+
|
|
13
|
+
if (ts.isComputedPropertyName(name)) {
|
|
14
|
+
if (ts.isStringLiteral(name.expression) || ts.isNumericLiteral(name.expression)) {
|
|
15
|
+
return `literal:${name.expression.text}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return `computed:${name.getText(file)}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (ts.isPrivateIdentifier(name)) {
|
|
22
|
+
return `private:${name.text}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return `literal:${name.text}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function belongsToOverload(signature: OverloadMember, following: OverloadMember, file: ts.SourceFile): boolean {
|
|
29
|
+
if (ts.isConstructorDeclaration(signature) || ts.isConstructorDeclaration(following)) {
|
|
30
|
+
return ts.isConstructorDeclaration(signature) && ts.isConstructorDeclaration(following);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const signatureStatic = ts.getCombinedModifierFlags(signature) & ts.ModifierFlags.Static;
|
|
34
|
+
const followingStatic = ts.getCombinedModifierFlags(following) & ts.ModifierFlags.Static;
|
|
35
|
+
|
|
36
|
+
return signatureStatic === followingStatic && methodName(signature, file) === methodName(following, file);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function findGroupedSignatures(members: readonly ts.ClassElement[], file: ts.SourceFile): Set<ts.ClassElement> {
|
|
40
|
+
const signatures = new Set<ts.ClassElement>();
|
|
41
|
+
let following: OverloadMember | undefined;
|
|
42
|
+
|
|
43
|
+
for (const member of members.toReversed()) {
|
|
44
|
+
if (isOverloadMember(member)) {
|
|
45
|
+
if (!member.body && following && belongsToOverload(member, following, file)) {
|
|
46
|
+
signatures.add(member);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
following = member;
|
|
50
|
+
} else {
|
|
51
|
+
following = undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return signatures;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function countBlankLines(previous: ts.ClassElement, current: ts.ClassElement, file: ts.SourceFile): number {
|
|
59
|
+
const trailingComments = ts.getTrailingCommentRanges(file.text, previous.end);
|
|
60
|
+
const previousEnd = trailingComments?.at(-1)?.end ?? previous.end;
|
|
61
|
+
const leadingComments = ts.getLeadingCommentRanges(file.text, previousEnd);
|
|
62
|
+
const currentStart = leadingComments?.[0]?.pos ?? current.getStart(file);
|
|
63
|
+
const gap = file.text.slice(previousEnd, currentStart);
|
|
64
|
+
|
|
65
|
+
return gap
|
|
66
|
+
.split(/\r?\n/)
|
|
67
|
+
.slice(1, -1)
|
|
68
|
+
.filter((line) => /^[^\S\r\n]*$/.test(line)).length;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function findMemberSpacingIssues(source: string, fileName: string): readonly MemberSpacingIssue[] {
|
|
72
|
+
const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true);
|
|
73
|
+
const issues: MemberSpacingIssue[] = [];
|
|
74
|
+
|
|
75
|
+
function visit(node: ts.Node): void {
|
|
76
|
+
if (ts.isClassLike(node)) {
|
|
77
|
+
const members = node.members.filter((member) => !ts.isSemicolonClassElement(member));
|
|
78
|
+
const signatures = findGroupedSignatures(members, file);
|
|
79
|
+
let previous: ts.ClassElement | undefined;
|
|
80
|
+
|
|
81
|
+
for (const member of members) {
|
|
82
|
+
if (previous) {
|
|
83
|
+
const inOverloadGroup = signatures.has(previous);
|
|
84
|
+
const requiredBlankLines = inOverloadGroup ? 0 : 1;
|
|
85
|
+
|
|
86
|
+
if (countBlankLines(previous, member, file) !== requiredBlankLines) {
|
|
87
|
+
const { line, character } = file.getLineAndCharacterOfPosition(member.getStart(file));
|
|
88
|
+
const message = inOverloadGroup
|
|
89
|
+
? 'Keep adjacent signatures and the implementation of an overload together.'
|
|
90
|
+
: 'Leave one blank line between class members.';
|
|
91
|
+
|
|
92
|
+
issues.push({ line: line + 1, column: character + 1, message });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
previous = member;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
ts.forEachChild(node, visit);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
visit(file);
|
|
104
|
+
|
|
105
|
+
return issues.sort((left, right) => left.line - right.line || left.column - right.column);
|
|
106
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "harness-author-style",
|
|
3
|
+
"lockfileVersion": 3,
|
|
4
|
+
"requires": true,
|
|
5
|
+
"packages": {
|
|
6
|
+
"": {
|
|
7
|
+
"name": "harness-author-style",
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@biomejs/biome": "2.5.15",
|
|
10
|
+
"typescript": "5.9.3",
|
|
11
|
+
"zod": "4.6.7"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=24"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"node_modules/@biomejs/biome": {
|
|
18
|
+
"version": "2.5.15",
|
|
19
|
+
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.15.tgz",
|
|
20
|
+
"integrity": "sha512-WZTW4slm/pdkh92K6t/3aEN++44JD1PQ7squ7RCMLI1flHGl43DVOIGXvCjHiZgBMO1V4uYxoFNtqrIA4qGuIQ==",
|
|
21
|
+
"dev": true,
|
|
22
|
+
"bin": {
|
|
23
|
+
"biome": "bin/biome"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=14.21.3"
|
|
27
|
+
},
|
|
28
|
+
"optionalDependencies": {
|
|
29
|
+
"@biomejs/cli-darwin-arm64": "2.5.15",
|
|
30
|
+
"@biomejs/cli-darwin-x64": "2.5.15",
|
|
31
|
+
"@biomejs/cli-linux-arm64": "2.5.15",
|
|
32
|
+
"@biomejs/cli-linux-arm64-musl": "2.5.15",
|
|
33
|
+
"@biomejs/cli-linux-x64": "2.5.15",
|
|
34
|
+
"@biomejs/cli-linux-x64-musl": "2.5.15",
|
|
35
|
+
"@biomejs/cli-win32-arm64": "2.5.15",
|
|
36
|
+
"@biomejs/cli-win32-x64": "2.5.15"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"node_modules/@biomejs/cli-darwin-arm64": {
|
|
40
|
+
"version": "2.5.15",
|
|
41
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.15.tgz",
|
|
42
|
+
"integrity": "sha512-BZVzFhJ/mUvTLMYbc9x6el0o2Uv5zP7bACYyhFb6fSc1giroXm7PL0a5KqMJ9F+/BnkYRjagD/ROSDVOZ6eapg==",
|
|
43
|
+
"cpu": [
|
|
44
|
+
"arm64"
|
|
45
|
+
],
|
|
46
|
+
"dev": true,
|
|
47
|
+
"optional": true,
|
|
48
|
+
"os": [
|
|
49
|
+
"darwin"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"node_modules/@biomejs/cli-darwin-x64": {
|
|
53
|
+
"version": "2.5.15",
|
|
54
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.15.tgz",
|
|
55
|
+
"integrity": "sha512-V5Kw63V+fVGNFhFrizDxMbGXAzZCh8kYzJpy3GI6gTapWDg7bZK9oYC9CbVgQSEdTnupz0U5Efz8Ev+5vdBBXw==",
|
|
56
|
+
"cpu": [
|
|
57
|
+
"x64"
|
|
58
|
+
],
|
|
59
|
+
"dev": true,
|
|
60
|
+
"optional": true,
|
|
61
|
+
"os": [
|
|
62
|
+
"darwin"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"node_modules/@biomejs/cli-linux-arm64": {
|
|
66
|
+
"version": "2.5.15",
|
|
67
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.15.tgz",
|
|
68
|
+
"integrity": "sha512-XaG7P7eeSLYETD3K9grfB0mQmpLQZjygdbsxekWBJAg4am79fGAtRpfRyNnTvXB2fZFNnJZG3nXm7HBat0+VUw==",
|
|
69
|
+
"cpu": [
|
|
70
|
+
"arm64"
|
|
71
|
+
],
|
|
72
|
+
"dev": true,
|
|
73
|
+
"libc": [
|
|
74
|
+
"glibc"
|
|
75
|
+
],
|
|
76
|
+
"optional": true,
|
|
77
|
+
"os": [
|
|
78
|
+
"linux"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"node_modules/@biomejs/cli-linux-arm64-musl": {
|
|
82
|
+
"version": "2.5.15",
|
|
83
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.15.tgz",
|
|
84
|
+
"integrity": "sha512-tGzZUTcJCV7tj5Adh/Gn6nR4MycqA3iohq2LEcrarAgRBkU0h0OKd2UzCRkOsOYOuUGaUJb4YmqRqyy2feGGSw==",
|
|
85
|
+
"cpu": [
|
|
86
|
+
"arm64"
|
|
87
|
+
],
|
|
88
|
+
"dev": true,
|
|
89
|
+
"libc": [
|
|
90
|
+
"musl"
|
|
91
|
+
],
|
|
92
|
+
"optional": true,
|
|
93
|
+
"os": [
|
|
94
|
+
"linux"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"node_modules/@biomejs/cli-linux-x64": {
|
|
98
|
+
"version": "2.5.15",
|
|
99
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.15.tgz",
|
|
100
|
+
"integrity": "sha512-xE4iEW/3LqlYj9GFgGrFsFSH51dEEpUbYWBfeOv0q87WkUDxK2o/HhreSb7qMJqck70RVM6Lg96hgedcAYcOkA==",
|
|
101
|
+
"cpu": [
|
|
102
|
+
"x64"
|
|
103
|
+
],
|
|
104
|
+
"dev": true,
|
|
105
|
+
"libc": [
|
|
106
|
+
"glibc"
|
|
107
|
+
],
|
|
108
|
+
"optional": true,
|
|
109
|
+
"os": [
|
|
110
|
+
"linux"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
"node_modules/@biomejs/cli-linux-x64-musl": {
|
|
114
|
+
"version": "2.5.15",
|
|
115
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.15.tgz",
|
|
116
|
+
"integrity": "sha512-IlxUcyxilVGPsE008x13pWdkTbU3nQpP2i9b5UrbOYj6goBkKsRX1XB7yJLcV+O1H9LBchIIm4adOaVLZBX0ZQ==",
|
|
117
|
+
"cpu": [
|
|
118
|
+
"x64"
|
|
119
|
+
],
|
|
120
|
+
"dev": true,
|
|
121
|
+
"libc": [
|
|
122
|
+
"musl"
|
|
123
|
+
],
|
|
124
|
+
"optional": true,
|
|
125
|
+
"os": [
|
|
126
|
+
"linux"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
"node_modules/@biomejs/cli-win32-arm64": {
|
|
130
|
+
"version": "2.5.15",
|
|
131
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.15.tgz",
|
|
132
|
+
"integrity": "sha512-2kPKzhNlm8C+Ru3GcO0Me2ODkCBLrVOUNuyi84RJyWDVKAA4+Kjj3jMjL938lF6BRfvltC4vB2nPY9SvN51Ovg==",
|
|
133
|
+
"cpu": [
|
|
134
|
+
"arm64"
|
|
135
|
+
],
|
|
136
|
+
"dev": true,
|
|
137
|
+
"optional": true,
|
|
138
|
+
"os": [
|
|
139
|
+
"win32"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"node_modules/@biomejs/cli-win32-x64": {
|
|
143
|
+
"version": "2.5.15",
|
|
144
|
+
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.15.tgz",
|
|
145
|
+
"integrity": "sha512-yAzh4UqEImV6Hcy0zjUqNfJAsUhoD64FBQCdTG8Md/Z2wQeVP/ZmJ3XRYAs1g8J9fjTFyl2fCtc5FB5til47+g==",
|
|
146
|
+
"cpu": [
|
|
147
|
+
"x64"
|
|
148
|
+
],
|
|
149
|
+
"dev": true,
|
|
150
|
+
"optional": true,
|
|
151
|
+
"os": [
|
|
152
|
+
"win32"
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
"node_modules/typescript": {
|
|
156
|
+
"version": "5.9.3",
|
|
157
|
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
158
|
+
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
|
159
|
+
"dev": true,
|
|
160
|
+
"license": "Apache-2.0",
|
|
161
|
+
"bin": {
|
|
162
|
+
"tsc": "bin/tsc",
|
|
163
|
+
"tsserver": "bin/tsserver"
|
|
164
|
+
},
|
|
165
|
+
"engines": {
|
|
166
|
+
"node": ">=14.17"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"node_modules/zod": {
|
|
170
|
+
"version": "4.6.7",
|
|
171
|
+
"resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz",
|
|
172
|
+
"integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==",
|
|
173
|
+
"dev": true,
|
|
174
|
+
"license": "MIT",
|
|
175
|
+
"funding": {
|
|
176
|
+
"url": "https://github.com/sponsors/colinhacks"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "harness-author-style",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"check": "node check.ts",
|
|
7
|
+
"test": "node --test *.test.ts"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=24"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@biomejs/biome": "2.5.15",
|
|
14
|
+
"typescript": "5.9.3",
|
|
15
|
+
"zod": "4.6.7"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
language js(typescript, jsx)
|
|
2
|
+
|
|
3
|
+
pattern property($modifiers) {
|
|
4
|
+
or {
|
|
5
|
+
JsPropertyClassMember(modifiers=$modifiers, name=$name),
|
|
6
|
+
TsPropertySignatureClassMember(modifiers=$modifiers, name=$name),
|
|
7
|
+
TsInitializedPropertySignatureClassMember(modifiers=$modifiers, name=$name)
|
|
8
|
+
} where { not $name <: JsPrivateClassMemberName() }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
pattern method($modifiers) {
|
|
12
|
+
or {
|
|
13
|
+
JsMethodClassMember(modifiers=$modifiers, name=$name),
|
|
14
|
+
JsGetterClassMember(modifiers=$modifiers, name=$name),
|
|
15
|
+
JsSetterClassMember(modifiers=$modifiers, name=$name),
|
|
16
|
+
TsMethodSignatureClassMember(modifiers=$modifiers, name=$name),
|
|
17
|
+
TsGetterSignatureClassMember(modifiers=$modifiers, name=$name),
|
|
18
|
+
TsSetterSignatureClassMember(modifiers=$modifiers, name=$name)
|
|
19
|
+
} where { not $name <: JsPrivateClassMemberName() }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pattern internal() {
|
|
23
|
+
contains TsAccessibilityModifier() as $accessibility where { $accessibility <: r"(?:private|protected)" }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pattern private_static_property() {
|
|
27
|
+
property($modifiers) where { $modifiers <: contains JsStaticModifier(), $modifiers <: internal() }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pattern public_static_property() {
|
|
31
|
+
property($modifiers) where { $modifiers <: contains JsStaticModifier(), not $modifiers <: internal() }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pattern private_static_method() {
|
|
35
|
+
method($modifiers) where { $modifiers <: contains JsStaticModifier(), $modifiers <: internal() }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pattern public_static_method() {
|
|
39
|
+
method($modifiers) where { $modifiers <: contains JsStaticModifier(), not $modifiers <: internal() }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pattern constructor_member() {
|
|
43
|
+
or {
|
|
44
|
+
JsConstructorClassMember(),
|
|
45
|
+
TsConstructorSignatureClassMember()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pattern private_property() {
|
|
50
|
+
property($modifiers) where { not $modifiers <: contains JsStaticModifier(), $modifiers <: internal() }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
pattern public_property() {
|
|
54
|
+
property($modifiers) where { not $modifiers <: contains JsStaticModifier(), not $modifiers <: internal() }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pattern private_method() {
|
|
58
|
+
method($modifiers) where { not $modifiers <: contains JsStaticModifier(), $modifiers <: internal() }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pattern public_method() {
|
|
62
|
+
method($modifiers) where { not $modifiers <: contains JsStaticModifier(), not $modifiers <: internal() }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
or {
|
|
66
|
+
property(),
|
|
67
|
+
method(),
|
|
68
|
+
constructor_member()
|
|
69
|
+
} as $second where {
|
|
70
|
+
$second <: after $first,
|
|
71
|
+
$first <: or {
|
|
72
|
+
property(),
|
|
73
|
+
method(),
|
|
74
|
+
constructor_member()
|
|
75
|
+
},
|
|
76
|
+
or {
|
|
77
|
+
and { $second <: private_static_property(), not $first <: private_static_property() },
|
|
78
|
+
and {
|
|
79
|
+
$second <: public_static_property(),
|
|
80
|
+
not $first <: or {
|
|
81
|
+
private_static_property(),
|
|
82
|
+
public_static_property()
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
and {
|
|
86
|
+
$second <: private_static_method(),
|
|
87
|
+
$first <: or {
|
|
88
|
+
public_static_method(),
|
|
89
|
+
constructor_member(),
|
|
90
|
+
private_property(),
|
|
91
|
+
public_property(),
|
|
92
|
+
private_method(),
|
|
93
|
+
public_method()
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
and {
|
|
97
|
+
$second <: public_static_method(),
|
|
98
|
+
$first <: or {
|
|
99
|
+
constructor_member(),
|
|
100
|
+
private_property(),
|
|
101
|
+
public_property(),
|
|
102
|
+
private_method(),
|
|
103
|
+
public_method()
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
and {
|
|
107
|
+
$second <: constructor_member(),
|
|
108
|
+
$first <: or {
|
|
109
|
+
private_property(),
|
|
110
|
+
public_property(),
|
|
111
|
+
private_method(),
|
|
112
|
+
public_method()
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
and {
|
|
116
|
+
$second <: private_property(),
|
|
117
|
+
$first <: or {
|
|
118
|
+
public_property(),
|
|
119
|
+
private_method(),
|
|
120
|
+
public_method()
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
and {
|
|
124
|
+
$second <: public_property(),
|
|
125
|
+
$first <: or {
|
|
126
|
+
private_method(),
|
|
127
|
+
public_method()
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
and { $second <: private_method(), $first <: public_method() }
|
|
131
|
+
},
|
|
132
|
+
register_diagnostic(span=$second, message="Follow the class member order. Move this member before the preceding group.", severity="error")
|
|
133
|
+
}
|