@cparra/apexdocs 3.0.0-beta.1 → 3.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.
Files changed (125) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +246 -650
  3. package/dist/cli/generate.js +74 -3095
  4. package/dist/defaults-BcE8DTat.js +13 -0
  5. package/dist/defaults-D07y_bq4.js +40 -0
  6. package/dist/defaults-gPzwP66p.js +14 -0
  7. package/dist/index.d.ts +49 -19
  8. package/dist/index.js +90 -2
  9. package/dist/logger-BEbUIfqN.js +3282 -0
  10. package/dist/logger-BGuf1PnL.js +3281 -0
  11. package/dist/logger-CWBRF2za.js +3284 -0
  12. package/dist/logger-CdBmDEN1.js +3283 -0
  13. package/dist/logger-Ce4QqPFR.js +3278 -0
  14. package/dist/logger-CyEVYaAC.js +3284 -0
  15. package/dist/logger-D7a83ycP.js +3277 -0
  16. package/dist/logger-DGaHeBKk.js +3279 -0
  17. package/dist/logger-Dqhl_lO_.js +3278 -0
  18. package/dist/logger-aySSWi0G.js +3280 -0
  19. package/dist/logger-qLCcAtiy.js +3284 -0
  20. package/examples/README.md +5 -0
  21. package/examples/docsify/README.md +17 -0
  22. package/examples/docsify/apexdocs.config.ts +13 -0
  23. package/examples/docsify/classes/ASampleClass.cls +57 -0
  24. package/examples/docsify/classes/CodeControl.cls +19 -0
  25. package/examples/docsify/classes/SampleClass.cls +95 -0
  26. package/examples/docsify/classes/SampleInterface.cls +17 -0
  27. package/examples/docsify/classes/SomeDto.cls +122 -0
  28. package/examples/docsify/docs/.nojekyll +0 -0
  29. package/examples/docsify/docs/README.md +25 -0
  30. package/examples/docsify/docs/_config.yml +1 -0
  31. package/examples/docsify/docs/index.html +22 -0
  32. package/examples/docsify/docs/miscellaneous/ASampleClass.md +88 -0
  33. package/examples/docsify/docs/miscellaneous/CodeControl.md +107 -0
  34. package/examples/docsify/docs/miscellaneous/SomeDto.md +244 -0
  35. package/examples/docsify/docs/sample-classes/SampleClass.md +171 -0
  36. package/examples/docsify/docs/sample-interfaces/SampleInterface.md +36 -0
  37. package/examples/docsify/package-lock.json +2459 -0
  38. package/examples/docsify/package.json +14 -0
  39. package/examples/imported/.forceignore +12 -0
  40. package/examples/imported/README.md +6 -0
  41. package/examples/imported/config/project-scratch-def.json +5 -0
  42. package/examples/imported/docs/index.md +109 -0
  43. package/examples/imported/docs/miscellaneous/BaseClass.md +13 -0
  44. package/examples/imported/docs/miscellaneous/MultiInheritanceClass.md +69 -0
  45. package/examples/imported/docs/miscellaneous/ParentInterface.md +12 -0
  46. package/examples/imported/docs/miscellaneous/ReferencedEnum.md +5 -0
  47. package/examples/imported/docs/miscellaneous/SampleException.md +21 -0
  48. package/examples/imported/docs/miscellaneous/SampleInterface.md +113 -0
  49. package/examples/imported/docs/miscellaneous/Url.md +308 -0
  50. package/examples/imported/docs/sample-enums/SampleEnum.md +33 -0
  51. package/examples/imported/docs/samplegroup/SampleClass.md +167 -0
  52. package/examples/imported/force-app/classes/BaseClass.cls +3 -0
  53. package/examples/imported/force-app/classes/MultiInheritanceClass.cls +1 -0
  54. package/examples/imported/force-app/classes/ParentInterface.cls +3 -0
  55. package/examples/imported/force-app/classes/ReferencedEnum.cls +3 -0
  56. package/examples/imported/force-app/classes/SampleInterface.cls +50 -0
  57. package/examples/imported/force-app/classes/Url.cls +196 -0
  58. package/examples/imported/package-lock.json +665 -0
  59. package/examples/imported/package.json +6 -0
  60. package/examples/imported/scripts/process-docs.mjs +16 -0
  61. package/examples/imported/sfdx-project.json +12 -0
  62. package/examples/markdown/README.md +7 -0
  63. package/examples/markdown/docs/miscellaneous/Url.md +10 -8
  64. package/examples/markdown/force-app/classes/Url.cls +3 -1
  65. package/examples/markdown-jsconfig/.forceignore +12 -0
  66. package/examples/markdown-jsconfig/README.md +9 -0
  67. package/examples/markdown-jsconfig/apexdocs.config.mjs +22 -0
  68. package/examples/markdown-jsconfig/config/project-scratch-def.json +5 -0
  69. package/examples/markdown-jsconfig/docs/index.md +12 -0
  70. package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +315 -0
  71. package/examples/markdown-jsconfig/force-app/classes/Url.cls +196 -0
  72. package/examples/markdown-jsconfig/package-lock.json +665 -0
  73. package/examples/markdown-jsconfig/package.json +15 -0
  74. package/examples/markdown-jsconfig/sfdx-project.json +12 -0
  75. package/examples/open-api/README.md +5 -0
  76. package/examples/open-api/docs/openapi.json +2 -570
  77. package/examples/vitepress/README.md +25 -0
  78. package/examples/vitepress/apexdocs.config.ts +9 -2
  79. package/examples/vitepress/docs/index.md +11 -11
  80. package/examples/vitepress/docs/miscellaneous/BaseClass.md +1 -1
  81. package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +2 -2
  82. package/examples/vitepress/docs/miscellaneous/SampleException.md +1 -1
  83. package/examples/vitepress/docs/miscellaneous/SampleInterface.md +6 -6
  84. package/examples/vitepress/docs/miscellaneous/Url.md +3 -3
  85. package/examples/vitepress/docs/sample-enums/SampleEnum.md +3 -3
  86. package/examples/vitepress/docs/samplegroup/SampleClass.md +5 -5
  87. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleClass.cls +73 -0
  88. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleEnum.cls +30 -0
  89. package/examples/vitepress/force-app/main/default/classes/feature-a/SampleException.cls +17 -0
  90. package/package.json +3 -3
  91. package/src/application/Apexdocs.ts +16 -19
  92. package/src/application/__tests__/apex-file-reader.spec.ts +108 -67
  93. package/src/application/apex-file-reader.ts +1 -0
  94. package/src/application/generators/openapi.ts +17 -13
  95. package/src/cli/args.ts +12 -3
  96. package/src/cli/commands/markdown.ts +15 -12
  97. package/src/cli/commands/openapi.ts +5 -5
  98. package/src/cli/generate.ts +20 -4
  99. package/src/core/markdown/__test__/generating-class-docs.spec.ts +15 -386
  100. package/src/core/markdown/__test__/generating-docs.spec.ts +378 -0
  101. package/src/core/markdown/__test__/generating-enum-docs.spec.ts +4 -328
  102. package/src/core/markdown/__test__/generating-interface-docs.spec.ts +4 -296
  103. package/src/core/markdown/__test__/generating-reference-guide.spec.ts +17 -1
  104. package/src/core/markdown/__test__/test-helpers.ts +3 -1
  105. package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +3 -1
  106. package/src/core/markdown/adapters/renderable-to-page-data.ts +6 -4
  107. package/src/core/markdown/generate-docs.ts +13 -15
  108. package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +290 -0
  109. package/src/core/markdown/reflection/__test__/helpers.ts +18 -0
  110. package/src/core/markdown/reflection/__test__/remove-excluded-tags.spec.ts +200 -0
  111. package/src/core/markdown/reflection/remove-excluded-tags.ts +168 -0
  112. package/src/core/markdown/reflection/{sort-members.ts → sort-types-and-members.ts} +7 -5
  113. package/src/core/markdown/templates/reference-guide.ts +2 -2
  114. package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +6 -3
  115. package/src/core/openapi/open-api-docs-processor.ts +3 -3
  116. package/src/core/openapi/parser.ts +5 -2
  117. package/src/core/shared/types.d.ts +18 -18
  118. package/src/defaults.ts +15 -3
  119. package/src/index.ts +88 -14
  120. package/src/util/error-logger.ts +36 -36
  121. package/src/util/logger.ts +18 -11
  122. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleClass.cls +0 -0
  123. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleEnum.cls +0 -0
  124. /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleException.cls +0 -0
  125. /package/examples/vitepress/force-app/main/default/classes/{SampleInterface.cls → feature-a/SampleInterface.cls} +0 -0
@@ -4,11 +4,27 @@ import * as E from 'fp-ts/Either';
4
4
  import { apexBundleFromRawString, generateDocs } from './test-helpers';
5
5
  import { ReferenceGuidePageData } from '../../shared/types';
6
6
 
7
- describe('Generates a Reference Guide', () => {
7
+ describe('When generating the Reference Guide', () => {
8
8
  beforeAll(() => {
9
9
  extendExpect();
10
10
  });
11
11
 
12
+ it('contains the correct default title by default', async () => {
13
+ const result = await generateDocs([])();
14
+
15
+ assertEither(result, (data) =>
16
+ expect((data.referenceGuide as ReferenceGuidePageData).content).toContain('# Apex Reference Guide'),
17
+ );
18
+ });
19
+
20
+ it('allows for the reference guide title to be configured', async () => {
21
+ const result = await generateDocs([], { referenceGuideTitle: 'Custom Title' })();
22
+
23
+ assertEither(result, (data) =>
24
+ expect((data.referenceGuide as ReferenceGuidePageData).content).toContain('# Custom Title'),
25
+ );
26
+ });
27
+
12
28
  it('returns a reference guide with links to all other files', async () => {
13
29
  const input1 = `
14
30
  public enum MyEnum {
@@ -15,9 +15,11 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config?: Partial
15
15
  targetDir: 'target',
16
16
  scope: ['global', 'public'],
17
17
  defaultGroupName: 'Miscellaneous',
18
- sortMembersAlphabetically: true,
18
+ sortAlphabetically: false,
19
19
  referenceGuideTemplate: referenceGuideTemplate,
20
20
  linkingStrategy: 'relative',
21
+ excludeTags: [],
22
+ referenceGuideTitle: 'Apex Reference Guide',
21
23
  ...config,
22
24
  });
23
25
  }
@@ -14,8 +14,10 @@ const defaultMarkdownGeneratorConfig: MarkdownGeneratorConfig = {
14
14
  namespace: '',
15
15
  defaultGroupName: 'Miscellaneous',
16
16
  referenceGuideTemplate: '',
17
- sortMembersAlphabetically: false,
17
+ sortAlphabetically: false,
18
18
  linkingStrategy: 'relative',
19
+ referenceGuideTitle: 'Apex Reference Guide',
20
+ excludeTags: [],
19
21
  };
20
22
 
21
23
  describe('Conversion from InterfaceMirror to InterfaceSource understandable by the templating engine', () => {
@@ -5,15 +5,16 @@ import { CompilationRequest, Template } from '../templates/template';
5
5
  import { enumMarkdownTemplate } from '../templates/enum-template';
6
6
  import { interfaceMarkdownTemplate } from '../templates/interface-template';
7
7
  import { classMarkdownTemplate } from '../templates/class-template';
8
- import { defaults } from '../../../defaults';
8
+ import { markdownDefaults } from '../../../defaults';
9
9
 
10
10
  export const convertToDocumentationBundle = (
11
+ referenceGuideTitle: string,
11
12
  referenceGuideTemplate: string,
12
13
  { referencesByGroup, renderables }: RenderableBundle,
13
14
  ): DocumentationBundle => ({
14
15
  referenceGuide: {
15
16
  frontmatter: null,
16
- content: referencesToReferenceGuideContent(referencesByGroup, referenceGuideTemplate),
17
+ content: referencesToReferenceGuideContent(referenceGuideTitle, referencesByGroup, referenceGuideTemplate),
17
18
  outputDocPath: 'index.md',
18
19
  },
19
20
  docs: renderables.map((renderable: Renderable) =>
@@ -22,6 +23,7 @@ export const convertToDocumentationBundle = (
22
23
  });
23
24
 
24
25
  function referencesToReferenceGuideContent(
26
+ referenceGuideTitle: string,
25
27
  references: { [key: string]: ReferenceGuideReference[] },
26
28
  template: string,
27
29
  ): string {
@@ -39,7 +41,7 @@ function referencesToReferenceGuideContent(
39
41
  return pipe(references, alphabetizeReferences, (references) =>
40
42
  compile({
41
43
  template: template,
42
- source: references,
44
+ source: { referenceGuideTitle: referenceGuideTitle, references },
43
45
  }),
44
46
  );
45
47
  }
@@ -59,7 +61,7 @@ function renderableToPageData(referenceGuideReference: ReferenceGuideReference[]
59
61
  outputDocPath: reference!.reference.outputDocPath,
60
62
  frontmatter: null,
61
63
  content: docContents,
62
- group: renderable.doc.group ?? defaults.defaultGroupName,
64
+ group: renderable.doc.group ?? markdownDefaults.defaultGroupName,
63
65
  };
64
66
  }
65
67
 
@@ -26,24 +26,16 @@ import { convertToDocumentationBundle } from './adapters/renderable-to-page-data
26
26
  import { filterScope } from './reflection/filter-scope';
27
27
  import { Template } from './templates/template';
28
28
  import { hookableTemplate } from './templates/hookable';
29
- import { sortMembers } from './reflection/sort-members';
29
+ import { sortTypesAndMembers } from './reflection/sort-types-and-members';
30
30
  import { isSkip } from '../shared/utils';
31
31
  import { parsedFilesToReferenceGuide } from './adapters/reference-guide';
32
+ import { removeExcludedTags } from './reflection/remove-excluded-tags';
32
33
 
33
- export type MarkdownGeneratorConfig = Pick<
34
+ export type MarkdownGeneratorConfig = Omit<
34
35
  UserDefinedMarkdownConfig,
35
- | 'targetDir'
36
- | 'scope'
37
- | 'namespace'
38
- | 'defaultGroupName'
39
- | 'transformReferenceGuide'
40
- | 'transformDocs'
41
- | 'transformDocPage'
42
- | 'transformReference'
43
- | 'linkingStrategy'
36
+ 'sourceDir' | 'targetGenerator' | 'includeMetadata'
44
37
  > & {
45
38
  referenceGuideTemplate: string;
46
- sortMembersAlphabetically: boolean;
47
39
  };
48
40
 
49
41
  export class HookError {
@@ -56,8 +48,13 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config: Markdown
56
48
  const filterOutOfScope = apply(filterScope, config.scope);
57
49
  const convertToReferences = apply(parsedFilesToReferenceGuide, config);
58
50
  const convertToRenderableBundle = apply(parsedFilesToRenderableBundle, config);
59
- const convertToDocumentationBundleForTemplate = apply(convertToDocumentationBundle, config.referenceGuideTemplate);
60
- const sortTypeMembers = apply(sortMembers, config.sortMembersAlphabetically);
51
+ const convertToDocumentationBundleForTemplate = apply(
52
+ convertToDocumentationBundle,
53
+ config.referenceGuideTitle,
54
+ config.referenceGuideTemplate,
55
+ );
56
+ const sort = apply(sortTypesAndMembers, config.sortAlphabetically);
57
+ const removeExcluded = apply(removeExcludedTags, config.excludeTags);
61
58
 
62
59
  return pipe(
63
60
  apexBundles,
@@ -65,7 +62,8 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config: Markdown
65
62
  TE.map(filterOutOfScope),
66
63
  TE.map(addInheritedMembersToTypes),
67
64
  TE.map(addInheritanceChainToTypes),
68
- TE.map(sortTypeMembers),
65
+ TE.map(sort),
66
+ TE.map(removeExcluded),
69
67
  TE.bindTo('parsedFiles'),
70
68
  TE.bind('references', ({ parsedFiles }) => TE.right(convertToReferences(parsedFiles))),
71
69
  TE.flatMap(({ parsedFiles, references }) => transformReferenceHook(config)({ references, parsedFiles })),
@@ -0,0 +1,290 @@
1
+ import { ClassMirror, EnumMirror, InterfaceMirror } from '@cparra/apex-reflection';
2
+ import { filterScope } from '../filter-scope';
3
+ import { parsedFileFromRawString } from './helpers';
4
+
5
+ describe('When filtering scope', () => {
6
+ it('filters out files with the @ignore annotation', () => {
7
+ const properties: [string, number][] = [
8
+ [
9
+ `
10
+ /**
11
+ * @ignore
12
+ */
13
+ global class MyClass {}
14
+ `,
15
+ 0,
16
+ ],
17
+ ['global class MyClass {}', 1],
18
+ ];
19
+
20
+ for (const [input, expected] of properties) {
21
+ const parsedFile = parsedFileFromRawString(input);
22
+
23
+ const result = filterScope(['global'], [parsedFile]);
24
+
25
+ expect(result).toHaveLength(expected);
26
+ }
27
+ });
28
+
29
+ describe('when scoping a class', () => {
30
+ it('filters out methods tagged with @ignore', () => {
31
+ const properties: [string, number][] = [
32
+ [
33
+ `
34
+ global class MyClass {
35
+ /**
36
+ * @ignore
37
+ */
38
+ global void myMethod() {}
39
+ }
40
+ `,
41
+ 0,
42
+ ],
43
+ [
44
+ `
45
+ global class MyClass {
46
+ global void myMethod() {}
47
+ }
48
+ `,
49
+ 1,
50
+ ],
51
+ ];
52
+
53
+ for (const [input, expected] of properties) {
54
+ const parsedFile = parsedFileFromRawString(input);
55
+
56
+ const result = filterScope(['global'], [parsedFile]);
57
+
58
+ expect((result[0].type as ClassMirror).methods).toHaveLength(expected);
59
+ }
60
+ });
61
+
62
+ it('filters out properties tagged with @ignore', () => {
63
+ const properties: [string, number][] = [
64
+ [
65
+ `
66
+ global class MyClass {
67
+ /**
68
+ * @ignore
69
+ */
70
+ global Integer myProperty { get; set; }
71
+ }
72
+ `,
73
+ 0,
74
+ ],
75
+ [
76
+ `
77
+ global class MyClass {
78
+ global Integer myProperty { get; set; }
79
+ }
80
+ `,
81
+ 1,
82
+ ],
83
+ ];
84
+
85
+ for (const [input, expected] of properties) {
86
+ const parsedFile = parsedFileFromRawString(input);
87
+
88
+ const result = filterScope(['global'], [parsedFile]);
89
+
90
+ expect((result[0].type as ClassMirror).properties).toHaveLength(expected);
91
+ }
92
+ });
93
+
94
+ it('filters out fields tagged with @ignore', () => {
95
+ const properties: [string, number][] = [
96
+ [
97
+ `
98
+ global class MyClass {
99
+ /**
100
+ * @ignore
101
+ */
102
+ global Integer myField;
103
+ }
104
+ `,
105
+ 0,
106
+ ],
107
+ [
108
+ `
109
+ global class MyClass {
110
+ global Integer myField;
111
+ }
112
+ `,
113
+ 1,
114
+ ],
115
+ ];
116
+
117
+ for (const [input, expected] of properties) {
118
+ const parsedFile = parsedFileFromRawString(input);
119
+
120
+ const result = filterScope(['global'], [parsedFile]);
121
+
122
+ expect((result[0].type as ClassMirror).fields).toHaveLength(expected);
123
+ }
124
+ });
125
+
126
+ it('filters out inner classes tagged with @ignore', () => {
127
+ const properties: [string, number][] = [
128
+ [
129
+ `
130
+ global class MyClass {
131
+ /**
132
+ * @ignore
133
+ */
134
+ global class InnerClass {}
135
+ }
136
+ `,
137
+ 0,
138
+ ],
139
+ [
140
+ `
141
+ global class MyClass {
142
+ global class InnerClass {}
143
+ }
144
+ `,
145
+ 1,
146
+ ],
147
+ ];
148
+
149
+ for (const [input, expected] of properties) {
150
+ const parsedFile = parsedFileFromRawString(input);
151
+
152
+ const result = filterScope(['global'], [parsedFile]);
153
+
154
+ expect((result[0].type as ClassMirror).classes).toHaveLength(expected);
155
+ }
156
+ });
157
+
158
+ it('filters out inner interfaces tagged with @ignore', () => {
159
+ const properties: [string, number][] = [
160
+ [
161
+ `
162
+ global class MyClass {
163
+ /**
164
+ * @ignore
165
+ */
166
+ global interface InnerInterface {}
167
+ }
168
+ `,
169
+ 0,
170
+ ],
171
+ [
172
+ `
173
+ global class MyClass {
174
+ global interface InnerInterface {}
175
+ }
176
+ `,
177
+ 1,
178
+ ],
179
+ ];
180
+
181
+ for (const [input, expected] of properties) {
182
+ const parsedFile = parsedFileFromRawString(input);
183
+
184
+ const result = filterScope(['global'], [parsedFile]);
185
+
186
+ expect((result[0].type as ClassMirror).interfaces).toHaveLength(expected);
187
+ }
188
+ });
189
+
190
+ it('filters out inner enums tagged with @ignore', () => {
191
+ const properties: [string, number][] = [
192
+ [
193
+ `
194
+ global class MyClass {
195
+ /**
196
+ * @ignore
197
+ */
198
+ global enum InnerEnum {}
199
+ }
200
+ `,
201
+ 0,
202
+ ],
203
+ [
204
+ `
205
+ global class MyClass {
206
+ global enum InnerEnum {}
207
+ }
208
+ `,
209
+ 1,
210
+ ],
211
+ ];
212
+
213
+ for (const [input, expected] of properties) {
214
+ const parsedFile = parsedFileFromRawString(input);
215
+
216
+ const result = filterScope(['global'], [parsedFile]);
217
+
218
+ expect((result[0].type as ClassMirror).enums).toHaveLength(expected);
219
+ }
220
+ });
221
+ });
222
+
223
+ describe('when scoping an interface', () => {
224
+ it('filters out methods tagged with @ignore', () => {
225
+ const properties: [string, number][] = [
226
+ [
227
+ `
228
+ global interface MyInterface {
229
+ /**
230
+ * @ignore
231
+ */
232
+ void myMethod();
233
+ }
234
+ `,
235
+ 0,
236
+ ],
237
+ [
238
+ `
239
+ global interface MyInterface {
240
+ void myMethod();
241
+ }
242
+ `,
243
+ 1,
244
+ ],
245
+ ];
246
+
247
+ for (const [input, expected] of properties) {
248
+ const parsedFile = parsedFileFromRawString(input);
249
+
250
+ const result = filterScope(['global'], [parsedFile]);
251
+
252
+ expect((result[0].type as InterfaceMirror).methods).toHaveLength(expected);
253
+ }
254
+ });
255
+ });
256
+
257
+ describe('when scoping an enum', () => {
258
+ it('never filters out enum values, even if tagged with @ignore', () => {
259
+ const properties: [string, number][] = [
260
+ [
261
+ `
262
+ global enum MyEnum {
263
+ /**
264
+ * @ignore
265
+ */
266
+ VALUE
267
+ }
268
+ `,
269
+ 1,
270
+ ],
271
+ [
272
+ `
273
+ global enum MyEnum {
274
+ VALUE
275
+ }
276
+ `,
277
+ 1,
278
+ ],
279
+ ];
280
+
281
+ for (const [input, expected] of properties) {
282
+ const parsedFile = parsedFileFromRawString(input);
283
+
284
+ const result = filterScope(['global'], [parsedFile]);
285
+
286
+ expect((result[0].type as EnumMirror).values).toHaveLength(expected);
287
+ }
288
+ });
289
+ });
290
+ });
@@ -0,0 +1,18 @@
1
+ import { ParsedFile } from '../../../shared/types';
2
+ import { reflect } from '@cparra/apex-reflection';
3
+
4
+ export function parsedFileFromRawString(raw: string): ParsedFile {
5
+ const { error, typeMirror } = reflect(raw);
6
+ if (error) {
7
+ throw new Error(error.message);
8
+ }
9
+
10
+ return {
11
+ source: {
12
+ filePath: 'test.cls',
13
+ name: typeMirror!.name,
14
+ type: typeMirror!.type_name,
15
+ },
16
+ type: typeMirror!,
17
+ };
18
+ }
@@ -0,0 +1,200 @@
1
+ import { parsedFileFromRawString } from './helpers';
2
+ import { removeExcludedTags } from '../remove-excluded-tags';
3
+ import { ClassMirror, InterfaceMirror } from '@cparra/apex-reflection';
4
+
5
+ describe('when removing excluded tags', () => {
6
+ describe('from any type', () => {
7
+ it('removes annotations', () => {
8
+ const tagsToExclude = ['group'];
9
+ const content = `
10
+ /**
11
+ * @group MyGroup
12
+ * @custom myCustomTag
13
+ */
14
+ global class MyClass {}
15
+ `;
16
+ const parsedFile = parsedFileFromRawString(content);
17
+
18
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
19
+
20
+ expect(result[0].type.docComment?.annotations).toHaveLength(1);
21
+ expect(result[0].type.docComment?.annotations[0].name).toBe('custom');
22
+ });
23
+
24
+ it('removes example annotations', () => {
25
+ const tagsToExclude = ['example'];
26
+ const content = `
27
+ /**
28
+ * @example
29
+ * This is my example
30
+ * public void myMethod() {}
31
+ */
32
+ global class MyClass {}
33
+ `;
34
+ const parsedFile = parsedFileFromRawString(content);
35
+
36
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
37
+
38
+ expect(result[0].type.docComment?.exampleAnnotation).toBeNull();
39
+ });
40
+
41
+ it('removes params annotations', () => {
42
+ const tagsToExclude = ['param'];
43
+ const content = `
44
+ /**
45
+ * @param myParam
46
+ * public void myMethod() {}
47
+ */
48
+ global class MyClass {}
49
+ `;
50
+ const parsedFile = parsedFileFromRawString(content);
51
+
52
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
53
+
54
+ expect(result[0].type.docComment?.paramAnnotations).toHaveLength(0);
55
+ });
56
+
57
+ it('removes the return annotation', () => {
58
+ const tagsToExclude = ['return'];
59
+ const content = `
60
+ /**
61
+ * @return myReturn
62
+ * public void myMethod() {}
63
+ */
64
+ global class MyClass {}
65
+ `;
66
+ const parsedFile = parsedFileFromRawString(content);
67
+
68
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
69
+
70
+ expect(result[0].type.docComment?.returnAnnotation).toBeNull();
71
+ });
72
+
73
+ it('removes the throws annotations', () => {
74
+ const tagsToExclude = ['throws'];
75
+ const content = `
76
+ /**
77
+ * @throws MyException
78
+ * public void myMethod() {}
79
+ */
80
+ global class MyClass {}
81
+ `;
82
+ const parsedFile = parsedFileFromRawString(content);
83
+
84
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
85
+
86
+ expect(result[0].type.docComment?.throwsAnnotations).toHaveLength(0);
87
+ });
88
+
89
+ it('removes the exception annotations', () => {
90
+ const tagsToExclude = ['exception'];
91
+ const content = `
92
+ /**
93
+ * @exception MyException
94
+ * public void myMethod() {}
95
+ */
96
+ global class MyClass {}
97
+ `;
98
+ const parsedFile = parsedFileFromRawString(content);
99
+
100
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
101
+
102
+ expect(result[0].type.docComment?.throwsAnnotations).toHaveLength(0);
103
+ });
104
+
105
+ it('removes descriptions', () => {
106
+ const tagsToExclude = ['description'];
107
+ const content = `
108
+ /**
109
+ * @description This is my description
110
+ * public void myMethod() {}
111
+ */
112
+ global class MyClass {}
113
+ `;
114
+ const parsedFile = parsedFileFromRawString(content);
115
+
116
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
117
+
118
+ expect(result[0].type.docComment?.description).toBe('');
119
+ expect(result[0].type.docComment?.descriptionLines).toHaveLength(0);
120
+ });
121
+ });
122
+
123
+ describe('from an interface', () => {
124
+ it('removes annotations from methods', () => {
125
+ const tagsToExclude = ['throws'];
126
+ const content = `
127
+ global interface MyInterface {
128
+ /**
129
+ * @throws MyException
130
+ */
131
+ void myMethod();
132
+ }
133
+ `;
134
+ const parsedFile = parsedFileFromRawString(content);
135
+
136
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
137
+
138
+ expect((result[0].type as InterfaceMirror).methods[0].docComment?.throwsAnnotations).toHaveLength(0);
139
+ });
140
+ });
141
+
142
+ describe('from a class', () => {
143
+ it('removes annotations from members', () => {
144
+ const tagsToExclude = ['throws'];
145
+ const content = `
146
+ global class MyClass {
147
+ /**
148
+ * @throws MyException
149
+ */
150
+ String myProperty {get; set;}
151
+
152
+ /**
153
+ * @throws MyException
154
+ */
155
+ String myField;
156
+ /**
157
+ * @throws MyException
158
+ */
159
+ void myMethod() {}
160
+
161
+ /**
162
+ * @throws MyException
163
+ */
164
+ MyClass() {}
165
+
166
+ /**
167
+ * @throws MyException
168
+ */
169
+ public enum MyEnum {}
170
+
171
+ /**
172
+ * @throws MyException
173
+ */
174
+ interface MyInnerInterface {}
175
+
176
+ /**
177
+ * @throws MyException
178
+ */
179
+ class MyInnerClass {}
180
+ }
181
+ `;
182
+ const parsedFile = parsedFileFromRawString(content);
183
+
184
+ const result = removeExcludedTags(tagsToExclude, [parsedFile]);
185
+
186
+ const classMirror = result[0].type as ClassMirror;
187
+ expect(classMirror.methods[0].docComment?.throwsAnnotations).toHaveLength(0);
188
+ expect(classMirror.properties[0].docComment?.throwsAnnotations).toHaveLength(0);
189
+ expect(classMirror.fields[0].docComment?.throwsAnnotations).toHaveLength(0);
190
+ expect(classMirror.constructors[0].docComment?.throwsAnnotations).toHaveLength(0);
191
+ expect(classMirror.enums[0].docComment?.throwsAnnotations).toHaveLength(0);
192
+ expect(classMirror.interfaces[0].docComment?.throwsAnnotations).toHaveLength(0);
193
+ expect(classMirror.classes[0].docComment?.throwsAnnotations).toHaveLength(0);
194
+ });
195
+ });
196
+ });
197
+
198
+ // fields
199
+ // inner interfaces
200
+ // inner classes