@api-extractor-tools/eslint-plugin 0.1.0-alpha.0 → 0.1.0-alpha.2
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/ARCHITECTURE.md +204 -0
- package/CHANGELOG.md +32 -0
- package/README.md +306 -10
- package/api-extractor.json +1 -0
- package/dist/configs/recommended.d.ts +1 -1
- package/dist/configs/recommended.d.ts.map +1 -1
- package/dist/configs/recommended.js +7 -1
- package/dist/configs/recommended.js.map +1 -1
- package/dist/index.d.ts +9 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -15
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +28 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +41 -0
- package/dist/node.js.map +1 -0
- package/dist/rules/extra-release-tag.d.ts +24 -0
- package/dist/rules/extra-release-tag.d.ts.map +1 -0
- package/dist/rules/extra-release-tag.js +141 -0
- package/dist/rules/extra-release-tag.js.map +1 -0
- package/dist/rules/forgotten-export.d.ts +24 -0
- package/dist/rules/forgotten-export.d.ts.map +1 -0
- package/dist/rules/forgotten-export.js +212 -0
- package/dist/rules/forgotten-export.js.map +1 -0
- package/dist/rules/incompatible-release-tags.d.ts +25 -0
- package/dist/rules/incompatible-release-tags.d.ts.map +1 -0
- package/dist/rules/incompatible-release-tags.js +237 -0
- package/dist/rules/incompatible-release-tags.js.map +1 -0
- package/dist/rules/index.d.ts +8 -2
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +13 -1
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/missing-release-tag.d.ts +4 -0
- package/dist/rules/missing-release-tag.d.ts.map +1 -1
- package/dist/rules/missing-release-tag.js +14 -21
- package/dist/rules/missing-release-tag.js.map +1 -1
- package/dist/rules/override-keyword.d.ts +4 -0
- package/dist/rules/override-keyword.d.ts.map +1 -1
- package/dist/rules/override-keyword.js +9 -11
- package/dist/rules/override-keyword.js.map +1 -1
- package/dist/rules/package-documentation.d.ts +5 -2
- package/dist/rules/package-documentation.d.ts.map +1 -1
- package/dist/rules/package-documentation.js +45 -35
- package/dist/rules/package-documentation.js.map +1 -1
- package/dist/rules/public-on-non-exported.d.ts +24 -0
- package/dist/rules/public-on-non-exported.d.ts.map +1 -0
- package/dist/rules/public-on-non-exported.js +191 -0
- package/dist/rules/public-on-non-exported.js.map +1 -0
- package/dist/rules/public-on-private-member.d.ts +24 -0
- package/dist/rules/public-on-private-member.d.ts.map +1 -0
- package/dist/rules/public-on-private-member.js +111 -0
- package/dist/rules/public-on-private-member.js.map +1 -0
- package/dist/rules/valid-enum-type.d.ts +17 -0
- package/dist/rules/valid-enum-type.d.ts.map +1 -0
- package/dist/rules/valid-enum-type.js +206 -0
- package/dist/rules/valid-enum-type.js.map +1 -0
- package/dist/types.d.ts +66 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/tsdoc-parser.d.ts +37 -6
- package/dist/utils/tsdoc-parser.d.ts.map +1 -1
- package/dist/utils/tsdoc-parser.js +40 -0
- package/dist/utils/tsdoc-parser.js.map +1 -1
- package/docs/rules/valid-enum-type.md +153 -0
- package/package.json +22 -8
- package/src/configs/recommended.ts +7 -1
- package/src/index.ts +21 -15
- package/src/node.ts +50 -0
- package/src/rules/extra-release-tag.ts +201 -0
- package/src/rules/forgotten-export.ts +274 -0
- package/src/rules/incompatible-release-tags.ts +331 -0
- package/src/rules/index.ts +13 -1
- package/src/rules/missing-release-tag.ts +11 -26
- package/src/rules/override-keyword.ts +6 -8
- package/src/rules/package-documentation.ts +54 -40
- package/src/rules/public-on-non-exported.ts +265 -0
- package/src/rules/public-on-private-member.ts +157 -0
- package/src/rules/valid-enum-type.ts +252 -0
- package/src/types.ts +60 -17
- package/src/utils/config-loader.ts +1 -0
- package/src/utils/entry-point.ts +1 -0
- package/src/utils/tsdoc-parser.ts +67 -0
- package/temp/eslint-plugin.api.md +101 -32
- package/test/index.test.ts +1 -0
- package/test/rules/extra-release-tag.test.ts +276 -0
- package/test/rules/forgotten-export.test.ts +190 -0
- package/test/rules/incompatible-release-tags.test.ts +340 -0
- package/test/rules/missing-release-tag.test.ts +2 -1
- package/test/rules/override-keyword.test.ts +2 -1
- package/test/rules/package-documentation.test.ts +113 -64
- package/test/rules/public-on-non-exported.test.ts +201 -0
- package/test/rules/public-on-private-member.test.ts +207 -0
- package/test/rules/valid-enum-type.test.ts +409 -0
- package/test/types.test-d.ts +20 -0
- package/test/utils/config-loader.test.ts +1 -0
- package/test/utils/tsdoc-parser.test.ts +117 -9
- package/tsconfig.json +1 -0
- package/vitest.config.mts +1 -0
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -21
- package/dist/utils/index.js.map +0 -1
- package/src/utils/index.ts +0 -17
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
|
|
7
|
+
import { DocComment } from '@microsoft/tsdoc';
|
|
8
|
+
import { ParserContext } from '@microsoft/tsdoc';
|
|
7
9
|
import { RuleListener } from '@typescript-eslint/utils/dist/ts-eslint';
|
|
8
10
|
import { RuleModule } from '@typescript-eslint/utils/dist/ts-eslint';
|
|
9
11
|
import type { TSESLint } from '@typescript-eslint/utils';
|
|
12
|
+
import type { TSESTree } from '@typescript-eslint/utils';
|
|
10
13
|
|
|
11
|
-
// @
|
|
14
|
+
// @alpha
|
|
12
15
|
export interface ApiExtractorConfig {
|
|
13
16
|
// (undocumented)
|
|
14
17
|
extends?: string;
|
|
@@ -18,7 +21,7 @@ export interface ApiExtractorConfig {
|
|
|
18
21
|
messages?: ApiExtractorMessagesConfig;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
// @
|
|
24
|
+
// @alpha
|
|
22
25
|
export interface ApiExtractorEslintPlugin {
|
|
23
26
|
// Warning: (ae-forgotten-export) The symbol "PluginConfigs" needs to be exported by the entry point index.d.ts
|
|
24
27
|
//
|
|
@@ -33,33 +36,82 @@ export interface ApiExtractorEslintPlugin {
|
|
|
33
36
|
rules: typeof rules;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
// @
|
|
37
|
-
export type ApiExtractorLogLevel = 'error' | '
|
|
39
|
+
// @alpha
|
|
40
|
+
export type ApiExtractorLogLevel = 'error' | 'none' | 'warning';
|
|
38
41
|
|
|
39
|
-
// @
|
|
42
|
+
// @alpha
|
|
40
43
|
export interface ApiExtractorMessagesConfig {
|
|
41
44
|
// (undocumented)
|
|
42
45
|
compilerMessageReporting?: {
|
|
43
|
-
default?: MessageConfig;
|
|
44
46
|
[messageId: string]: MessageConfig | undefined;
|
|
47
|
+
default?: MessageConfig;
|
|
45
48
|
};
|
|
46
49
|
// (undocumented)
|
|
47
50
|
extractorMessageReporting?: {
|
|
48
|
-
|
|
49
|
-
'ae-missing-release-tag'?: MessageConfig;
|
|
51
|
+
'ae-extra-release-tag'?: MessageConfig;
|
|
50
52
|
'ae-forgotten-export'?: MessageConfig;
|
|
51
|
-
'ae-internal-missing-underscore'?: MessageConfig;
|
|
52
53
|
'ae-incompatible-release-tags'?: MessageConfig;
|
|
54
|
+
'ae-internal-missing-underscore'?: MessageConfig;
|
|
55
|
+
'ae-missing-release-tag'?: MessageConfig;
|
|
53
56
|
[messageId: string]: MessageConfig | undefined;
|
|
57
|
+
default?: MessageConfig;
|
|
54
58
|
};
|
|
55
59
|
// (undocumented)
|
|
56
60
|
tsdocMessageReporting?: {
|
|
57
|
-
default?: MessageConfig;
|
|
58
61
|
[messageId: string]: MessageConfig | undefined;
|
|
62
|
+
default?: MessageConfig;
|
|
59
63
|
};
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
// @
|
|
66
|
+
// @alpha
|
|
67
|
+
export interface EnumTypeExtraction {
|
|
68
|
+
count: number;
|
|
69
|
+
found: boolean;
|
|
70
|
+
isValid: boolean;
|
|
71
|
+
rawValue?: string;
|
|
72
|
+
value?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// @alpha
|
|
76
|
+
export type EnumTypeValue = 'closed' | 'open';
|
|
77
|
+
|
|
78
|
+
// @alpha
|
|
79
|
+
export function extractEnumType(commentText: string): EnumTypeExtraction;
|
|
80
|
+
|
|
81
|
+
// @alpha
|
|
82
|
+
export function extractReleaseTag(docComment: DocComment): ReleaseTag | undefined;
|
|
83
|
+
|
|
84
|
+
// @alpha
|
|
85
|
+
export interface ExtraReleaseTagRuleOptions {
|
|
86
|
+
severity?: ApiExtractorLogLevel;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// @alpha
|
|
90
|
+
export function findAllTSDocComments(sourceCode: { getAllComments: () => TSESTree.Comment[] }): Array<{
|
|
91
|
+
comment: TSESTree.Comment;
|
|
92
|
+
parsed: ParserContext;
|
|
93
|
+
}>;
|
|
94
|
+
|
|
95
|
+
// @alpha
|
|
96
|
+
export interface ForgottenExportRuleOptions {
|
|
97
|
+
severity?: ApiExtractorLogLevel;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// @alpha
|
|
101
|
+
export function getLeadingTSDocComment(sourceCode: { getCommentsBefore: (node: TSESTree.Node) => TSESTree.Comment[] }, node: TSESTree.Node): string | undefined;
|
|
102
|
+
|
|
103
|
+
// @alpha @override
|
|
104
|
+
export function hasOverrideTag(docComment: DocComment): boolean;
|
|
105
|
+
|
|
106
|
+
// @alpha
|
|
107
|
+
export function hasPackageDocumentation(docComment: DocComment): boolean;
|
|
108
|
+
|
|
109
|
+
// @alpha
|
|
110
|
+
export interface IncompatibleReleaseTagsRuleOptions {
|
|
111
|
+
severity?: ApiExtractorLogLevel;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// @alpha
|
|
63
115
|
export interface MessageConfig {
|
|
64
116
|
// (undocumented)
|
|
65
117
|
addToApiReportFile?: boolean;
|
|
@@ -67,38 +119,44 @@ export interface MessageConfig {
|
|
|
67
119
|
logLevel: ApiExtractorLogLevel;
|
|
68
120
|
}
|
|
69
121
|
|
|
70
|
-
// @
|
|
122
|
+
// @alpha
|
|
71
123
|
export interface MissingReleaseTagRuleOptions {
|
|
72
|
-
|
|
73
|
-
configPath?: string;
|
|
124
|
+
severity?: ApiExtractorLogLevel;
|
|
74
125
|
}
|
|
75
126
|
|
|
76
|
-
// @
|
|
77
|
-
export
|
|
78
|
-
// (undocumented)
|
|
79
|
-
configPath?: string;
|
|
80
|
-
}
|
|
127
|
+
// @alpha
|
|
128
|
+
export type OverrideKeywordRuleOptions = Record<string, never>;
|
|
81
129
|
|
|
82
|
-
// @
|
|
83
|
-
export
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
130
|
+
// @alpha
|
|
131
|
+
export type PackageDocumentationRuleOptions = Record<string, never>;
|
|
132
|
+
|
|
133
|
+
// @alpha
|
|
134
|
+
export function parseTSDocComment(commentText: string): ParserContext;
|
|
87
135
|
|
|
88
|
-
// @
|
|
136
|
+
// @alpha
|
|
89
137
|
const plugin: ApiExtractorEslintPlugin;
|
|
90
138
|
export default plugin;
|
|
91
139
|
|
|
92
|
-
// @
|
|
140
|
+
// @alpha
|
|
141
|
+
export interface PublicOnNonExportedRuleOptions {
|
|
142
|
+
severity?: ApiExtractorLogLevel;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// @alpha
|
|
146
|
+
export interface PublicOnPrivateMemberRuleOptions {
|
|
147
|
+
severity?: ApiExtractorLogLevel;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// @alpha
|
|
93
151
|
export const recommendedRules: TSESLint.Linter.RulesRecord;
|
|
94
152
|
|
|
95
|
-
// @
|
|
153
|
+
// @alpha
|
|
96
154
|
export const RELEASE_TAGS: readonly ReleaseTag[];
|
|
97
155
|
|
|
98
|
-
// @
|
|
99
|
-
export type ReleaseTag = '
|
|
156
|
+
// @alpha
|
|
157
|
+
export type ReleaseTag = 'alpha' | 'beta' | 'internal' | 'public';
|
|
100
158
|
|
|
101
|
-
// @
|
|
159
|
+
// @alpha
|
|
102
160
|
export interface ResolvedEntryPoints {
|
|
103
161
|
// (undocumented)
|
|
104
162
|
exports: string[];
|
|
@@ -108,11 +166,22 @@ export interface ResolvedEntryPoints {
|
|
|
108
166
|
types?: string;
|
|
109
167
|
}
|
|
110
168
|
|
|
111
|
-
// @
|
|
169
|
+
// @alpha
|
|
112
170
|
export const rules: {
|
|
171
|
+
readonly 'extra-release-tag': RuleModule<"extraReleaseTag", [ExtraReleaseTagRuleOptions], unknown, RuleListener>;
|
|
172
|
+
readonly 'forgotten-export': RuleModule<"forgottenExport", [ForgottenExportRuleOptions], unknown, RuleListener>;
|
|
173
|
+
readonly 'incompatible-release-tags': RuleModule<"incompatibleReleaseTags", [IncompatibleReleaseTagsRuleOptions], unknown, RuleListener>;
|
|
113
174
|
readonly 'missing-release-tag': RuleModule<"missingReleaseTag", [MissingReleaseTagRuleOptions], unknown, RuleListener>;
|
|
114
175
|
readonly 'override-keyword': RuleModule<"missingOverrideKeyword", [OverrideKeywordRuleOptions], unknown, RuleListener>;
|
|
115
|
-
readonly 'package-documentation': RuleModule<"missingPackageDocumentation", [PackageDocumentationRuleOptions], unknown, RuleListener>;
|
|
176
|
+
readonly 'package-documentation': RuleModule<"missingPackageDocumentation" | "unexpectedPackageDocumentation", [PackageDocumentationRuleOptions], unknown, RuleListener>;
|
|
177
|
+
readonly 'public-on-non-exported': RuleModule<"publicOnNonExported", [PublicOnNonExportedRuleOptions], unknown, RuleListener>;
|
|
178
|
+
readonly 'public-on-private-member': RuleModule<"publicOnPrivateMember", [PublicOnPrivateMemberRuleOptions], unknown, RuleListener>;
|
|
179
|
+
readonly 'valid-enum-type': RuleModule<"missingValue" | "invalidValue" | "multipleEnumTypes" | "invalidConstruct" | "missingEnumType", [ValidEnumTypeRuleOptions], unknown, RuleListener>;
|
|
116
180
|
};
|
|
117
181
|
|
|
182
|
+
// @alpha
|
|
183
|
+
export interface ValidEnumTypeRuleOptions {
|
|
184
|
+
requireOnExported?: boolean;
|
|
185
|
+
}
|
|
186
|
+
|
|
118
187
|
```
|
package/test/index.test.ts
CHANGED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
2
|
+
import { describe, it, afterAll } from 'vitest'
|
|
3
|
+
import * as tseslintParser from '@typescript-eslint/parser'
|
|
4
|
+
import { extraReleaseTag } from '../../src/rules/extra-release-tag'
|
|
5
|
+
|
|
6
|
+
RuleTester.afterAll = afterAll
|
|
7
|
+
RuleTester.describe = describe
|
|
8
|
+
RuleTester.it = it
|
|
9
|
+
|
|
10
|
+
const ruleTester = new RuleTester({
|
|
11
|
+
languageOptions: {
|
|
12
|
+
parser: tseslintParser,
|
|
13
|
+
parserOptions: {
|
|
14
|
+
ecmaVersion: 2022,
|
|
15
|
+
sourceType: 'module',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
describe('extra-release-tag', () => {
|
|
21
|
+
ruleTester.run('extra-release-tag', extraReleaseTag, {
|
|
22
|
+
valid: [
|
|
23
|
+
// Single @public tag
|
|
24
|
+
{
|
|
25
|
+
code: `
|
|
26
|
+
/**
|
|
27
|
+
* A public function.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export function myFunction(): void {}
|
|
31
|
+
`,
|
|
32
|
+
},
|
|
33
|
+
// Single @beta tag
|
|
34
|
+
{
|
|
35
|
+
code: `
|
|
36
|
+
/**
|
|
37
|
+
* A beta function.
|
|
38
|
+
* @beta
|
|
39
|
+
*/
|
|
40
|
+
export function myBetaFunction(): void {}
|
|
41
|
+
`,
|
|
42
|
+
},
|
|
43
|
+
// Single @alpha tag
|
|
44
|
+
{
|
|
45
|
+
code: `
|
|
46
|
+
/**
|
|
47
|
+
* An alpha function.
|
|
48
|
+
* @alpha
|
|
49
|
+
*/
|
|
50
|
+
export function myAlphaFunction(): void {}
|
|
51
|
+
`,
|
|
52
|
+
},
|
|
53
|
+
// Single @internal tag
|
|
54
|
+
{
|
|
55
|
+
code: `
|
|
56
|
+
/**
|
|
57
|
+
* An internal function.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export function myInternalFunction(): void {}
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
// No release tag
|
|
64
|
+
{
|
|
65
|
+
code: `
|
|
66
|
+
/**
|
|
67
|
+
* A function without release tag.
|
|
68
|
+
*/
|
|
69
|
+
export function myFunction(): void {}
|
|
70
|
+
`,
|
|
71
|
+
},
|
|
72
|
+
// Single tag on class
|
|
73
|
+
{
|
|
74
|
+
code: `
|
|
75
|
+
/**
|
|
76
|
+
* A public class.
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
export class MyClass {}
|
|
80
|
+
`,
|
|
81
|
+
},
|
|
82
|
+
// Single tag on interface
|
|
83
|
+
{
|
|
84
|
+
code: `
|
|
85
|
+
/**
|
|
86
|
+
* A public interface.
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
export interface MyInterface {}
|
|
90
|
+
`,
|
|
91
|
+
},
|
|
92
|
+
// Single tag on type alias
|
|
93
|
+
{
|
|
94
|
+
code: `
|
|
95
|
+
/**
|
|
96
|
+
* A public type.
|
|
97
|
+
* @public
|
|
98
|
+
*/
|
|
99
|
+
export type MyType = string;
|
|
100
|
+
`,
|
|
101
|
+
},
|
|
102
|
+
// Single tag on enum
|
|
103
|
+
{
|
|
104
|
+
code: `
|
|
105
|
+
/**
|
|
106
|
+
* A public enum.
|
|
107
|
+
* @public
|
|
108
|
+
*/
|
|
109
|
+
export enum MyEnum { A, B }
|
|
110
|
+
`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
invalid: [
|
|
114
|
+
// Both @public and @beta
|
|
115
|
+
{
|
|
116
|
+
code: `
|
|
117
|
+
/**
|
|
118
|
+
* A function with multiple tags.
|
|
119
|
+
* @public
|
|
120
|
+
* @beta
|
|
121
|
+
*/
|
|
122
|
+
export function myFunction(): void {}
|
|
123
|
+
`,
|
|
124
|
+
errors: [
|
|
125
|
+
{
|
|
126
|
+
messageId: 'extraReleaseTag',
|
|
127
|
+
data: {
|
|
128
|
+
name: 'myFunction',
|
|
129
|
+
tags: '@public, @beta',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
// Both @public and @alpha
|
|
135
|
+
{
|
|
136
|
+
code: `
|
|
137
|
+
/**
|
|
138
|
+
* A function with multiple tags.
|
|
139
|
+
* @public
|
|
140
|
+
* @alpha
|
|
141
|
+
*/
|
|
142
|
+
export function myFunction(): void {}
|
|
143
|
+
`,
|
|
144
|
+
errors: [
|
|
145
|
+
{
|
|
146
|
+
messageId: 'extraReleaseTag',
|
|
147
|
+
data: {
|
|
148
|
+
name: 'myFunction',
|
|
149
|
+
tags: '@public, @alpha',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
// Both @beta and @internal
|
|
155
|
+
{
|
|
156
|
+
code: `
|
|
157
|
+
/**
|
|
158
|
+
* A function with multiple tags.
|
|
159
|
+
* @beta
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
export function myFunction(): void {}
|
|
163
|
+
`,
|
|
164
|
+
errors: [
|
|
165
|
+
{
|
|
166
|
+
messageId: 'extraReleaseTag',
|
|
167
|
+
data: {
|
|
168
|
+
name: 'myFunction',
|
|
169
|
+
tags: '@beta, @internal',
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
// Three tags
|
|
175
|
+
{
|
|
176
|
+
code: `
|
|
177
|
+
/**
|
|
178
|
+
* A function with three tags.
|
|
179
|
+
* @public
|
|
180
|
+
* @beta
|
|
181
|
+
* @alpha
|
|
182
|
+
*/
|
|
183
|
+
export function myFunction(): void {}
|
|
184
|
+
`,
|
|
185
|
+
errors: [
|
|
186
|
+
{
|
|
187
|
+
messageId: 'extraReleaseTag',
|
|
188
|
+
data: {
|
|
189
|
+
name: 'myFunction',
|
|
190
|
+
tags: '@public, @beta, @alpha',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
// Multiple tags on class
|
|
196
|
+
{
|
|
197
|
+
code: `
|
|
198
|
+
/**
|
|
199
|
+
* A class with multiple tags.
|
|
200
|
+
* @public
|
|
201
|
+
* @internal
|
|
202
|
+
*/
|
|
203
|
+
export class MyClass {}
|
|
204
|
+
`,
|
|
205
|
+
errors: [
|
|
206
|
+
{
|
|
207
|
+
messageId: 'extraReleaseTag',
|
|
208
|
+
data: {
|
|
209
|
+
name: 'MyClass',
|
|
210
|
+
tags: '@public, @internal',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
// Multiple tags on interface
|
|
216
|
+
{
|
|
217
|
+
code: `
|
|
218
|
+
/**
|
|
219
|
+
* An interface with multiple tags.
|
|
220
|
+
* @beta
|
|
221
|
+
* @alpha
|
|
222
|
+
*/
|
|
223
|
+
export interface MyInterface {}
|
|
224
|
+
`,
|
|
225
|
+
errors: [
|
|
226
|
+
{
|
|
227
|
+
messageId: 'extraReleaseTag',
|
|
228
|
+
data: {
|
|
229
|
+
name: 'MyInterface',
|
|
230
|
+
tags: '@beta, @alpha',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
// Multiple tags on type alias
|
|
236
|
+
{
|
|
237
|
+
code: `
|
|
238
|
+
/**
|
|
239
|
+
* A type with multiple tags.
|
|
240
|
+
* @public
|
|
241
|
+
* @beta
|
|
242
|
+
*/
|
|
243
|
+
export type MyType = string;
|
|
244
|
+
`,
|
|
245
|
+
errors: [
|
|
246
|
+
{
|
|
247
|
+
messageId: 'extraReleaseTag',
|
|
248
|
+
data: {
|
|
249
|
+
name: 'MyType',
|
|
250
|
+
tags: '@public, @beta',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
// Test with severity option
|
|
259
|
+
ruleTester.run('extra-release-tag with severity=none', extraReleaseTag, {
|
|
260
|
+
valid: [
|
|
261
|
+
// Should not report when severity is 'none'
|
|
262
|
+
{
|
|
263
|
+
code: `
|
|
264
|
+
/**
|
|
265
|
+
* A function with multiple tags.
|
|
266
|
+
* @public
|
|
267
|
+
* @beta
|
|
268
|
+
*/
|
|
269
|
+
export function myFunction(): void {}
|
|
270
|
+
`,
|
|
271
|
+
options: [{ severity: 'none' }],
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
invalid: [],
|
|
275
|
+
})
|
|
276
|
+
})
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
2
|
+
import { describe, it, afterAll } from 'vitest'
|
|
3
|
+
import * as tseslintParser from '@typescript-eslint/parser'
|
|
4
|
+
import { forgottenExport } from '../../src/rules/forgotten-export'
|
|
5
|
+
|
|
6
|
+
RuleTester.afterAll = afterAll
|
|
7
|
+
RuleTester.describe = describe
|
|
8
|
+
RuleTester.it = it
|
|
9
|
+
|
|
10
|
+
const ruleTester = new RuleTester({
|
|
11
|
+
languageOptions: {
|
|
12
|
+
parser: tseslintParser,
|
|
13
|
+
parserOptions: {
|
|
14
|
+
ecmaVersion: 2022,
|
|
15
|
+
sourceType: 'module',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
describe('forgotten-export', () => {
|
|
21
|
+
ruleTester.run('forgotten-export', forgottenExport, {
|
|
22
|
+
valid: [
|
|
23
|
+
// Both the interface and function are exported
|
|
24
|
+
{
|
|
25
|
+
code: `
|
|
26
|
+
export interface MyInterface {
|
|
27
|
+
name: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function myFunction(param: MyInterface): void {}
|
|
31
|
+
`,
|
|
32
|
+
},
|
|
33
|
+
// Using only built-in types
|
|
34
|
+
{
|
|
35
|
+
code: `
|
|
36
|
+
export function myFunction(param: string): number {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
`,
|
|
40
|
+
},
|
|
41
|
+
// Type is not defined in the file (imported or built-in)
|
|
42
|
+
{
|
|
43
|
+
code: `
|
|
44
|
+
export function myFunction(param: Date): void {}
|
|
45
|
+
`,
|
|
46
|
+
},
|
|
47
|
+
// Exported type alias
|
|
48
|
+
{
|
|
49
|
+
code: `
|
|
50
|
+
export type MyType = string;
|
|
51
|
+
|
|
52
|
+
export function myFunction(param: MyType): void {}
|
|
53
|
+
`,
|
|
54
|
+
},
|
|
55
|
+
// Exported class
|
|
56
|
+
{
|
|
57
|
+
code: `
|
|
58
|
+
export class MyClass {
|
|
59
|
+
value: string = '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function useClass(c: MyClass): void {}
|
|
63
|
+
`,
|
|
64
|
+
},
|
|
65
|
+
// Using generic built-in types
|
|
66
|
+
{
|
|
67
|
+
code: `
|
|
68
|
+
export function myFunction(): Promise<void> {
|
|
69
|
+
return Promise.resolve();
|
|
70
|
+
}
|
|
71
|
+
`,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
invalid: [
|
|
75
|
+
// Interface used but not exported
|
|
76
|
+
{
|
|
77
|
+
code: `
|
|
78
|
+
interface MyInterface {
|
|
79
|
+
name: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function myFunction(param: MyInterface): void {}
|
|
83
|
+
`,
|
|
84
|
+
errors: [
|
|
85
|
+
{
|
|
86
|
+
messageId: 'forgottenExport',
|
|
87
|
+
data: {
|
|
88
|
+
name: 'MyInterface',
|
|
89
|
+
exportedName: 'myFunction',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
// Type alias used but not exported
|
|
95
|
+
{
|
|
96
|
+
code: `
|
|
97
|
+
type MyType = string;
|
|
98
|
+
|
|
99
|
+
export function myFunction(param: MyType): void {}
|
|
100
|
+
`,
|
|
101
|
+
errors: [
|
|
102
|
+
{
|
|
103
|
+
messageId: 'forgottenExport',
|
|
104
|
+
data: {
|
|
105
|
+
name: 'MyType',
|
|
106
|
+
exportedName: 'myFunction',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
// Class used but not exported
|
|
112
|
+
{
|
|
113
|
+
code: `
|
|
114
|
+
class MyClass {
|
|
115
|
+
value: string = '';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function useClass(c: MyClass): void {}
|
|
119
|
+
`,
|
|
120
|
+
errors: [
|
|
121
|
+
{
|
|
122
|
+
messageId: 'forgottenExport',
|
|
123
|
+
data: {
|
|
124
|
+
name: 'MyClass',
|
|
125
|
+
exportedName: 'useClass',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
// Return type not exported
|
|
131
|
+
{
|
|
132
|
+
code: `
|
|
133
|
+
interface Result {
|
|
134
|
+
success: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function getResult(): Result {
|
|
138
|
+
return { success: true };
|
|
139
|
+
}
|
|
140
|
+
`,
|
|
141
|
+
errors: [
|
|
142
|
+
{
|
|
143
|
+
messageId: 'forgottenExport',
|
|
144
|
+
data: {
|
|
145
|
+
name: 'Result',
|
|
146
|
+
exportedName: 'getResult',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
// Type used in exported interface
|
|
152
|
+
{
|
|
153
|
+
code: `
|
|
154
|
+
type InternalType = string;
|
|
155
|
+
|
|
156
|
+
export interface MyInterface {
|
|
157
|
+
value: InternalType;
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
errors: [
|
|
161
|
+
{
|
|
162
|
+
messageId: 'forgottenExport',
|
|
163
|
+
data: {
|
|
164
|
+
name: 'InternalType',
|
|
165
|
+
exportedName: 'MyInterface',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
// Test with severity option
|
|
174
|
+
ruleTester.run('forgotten-export with severity=none', forgottenExport, {
|
|
175
|
+
valid: [
|
|
176
|
+
// Should not report when severity is 'none'
|
|
177
|
+
{
|
|
178
|
+
code: `
|
|
179
|
+
interface MyInterface {
|
|
180
|
+
name: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function myFunction(param: MyInterface): void {}
|
|
184
|
+
`,
|
|
185
|
+
options: [{ severity: 'none' }],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
invalid: [],
|
|
189
|
+
})
|
|
190
|
+
})
|