Skip to content

Commit 61149b0

Browse files
committed
Implement intentionallyNotDocumented option
Resolves #2863
1 parent 927f06d commit 61149b0

File tree

9 files changed

+74
-5
lines changed

9 files changed

+74
-5
lines changed

Diff for: site/options/package-options.md

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ at the root level. The following tables indicate where an option should be set.
143143
| [`treatValidationWarningsAsErrors`](validation.md#treatvalidationwarningsaserrors) | Root | |
144144
| [`intentionallyNotExported`](validation.md#intentionallynotexported) | Both | |
145145
| [`requiredToBeDocumented`](validation.md#requiredtobedocumented) | Both | |
146+
| [`intentionallyNotDocumented`](validation.md#intentionallynotdocumented) | Both | |
146147

147148
## Other Options
148149

Diff for: site/options/validation.md

+12
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,15 @@ typedoc.json:
123123
]
124124
}
125125
```
126+
127+
## intentionallyNotDocumented
128+
129+
Used to selectively ignore undocumented fields, used by `validation.notDocumented`.
130+
This should include the qualified name printed when a member is not documented if it cannot be
131+
or should not be documented normally.
132+
133+
```json
134+
{
135+
"intentionallyNotDocumented": ["Namespace.Class.prop"]
136+
}
137+
```

Diff for: src/lib/application.ts

+1
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ export class Application extends AbstractComponent<
685685
project,
686686
this.logger,
687687
this.options.getValue("requiredToBeDocumented"),
688+
this.options.getValue("intentionallyNotDocumented"),
688689
);
689690
}
690691

Diff for: src/lib/internationalization/locales/en.cts

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ export = {
9494
failed_to_resolve_link_to_0_in_document_1_may_have_meant_2: `Failed to resolve link to "{0}" in document {1}. You may have wanted "{2}"`,
9595
type_0_defined_in_1_is_referenced_by_2_but_not_included_in_docs: `{0}, defined in {1}, is referenced by {2} but not included in the documentation`,
9696
reflection_0_kind_1_defined_in_2_does_not_have_any_documentation: `{0} ({1}), defined in {2}, does not have any documentation`,
97+
invalid_intentionally_not_documented_names_0:
98+
"The following qualified reflection names were marked as intentionally not documented, but were either not referenced in the documentation, or were documented:\n\t{0}",
9799
invalid_intentionally_not_exported_symbols_0:
98100
"The following symbols were marked as intentionally not exported, but were either not referenced in the documentation, or were exported:\n\t{0}",
99101
reflection_0_has_unused_mergeModuleWith_tag:
@@ -375,6 +377,8 @@ export = {
375377
"A list of types which should not produce 'referenced but not documented' warnings",
376378
help_requiredToBeDocumented:
377379
"A list of reflection kinds that must be documented",
380+
help_intentionallyNotDocumented:
381+
"A list of full reflection names which should not produce warnings about not being documented",
378382
help_validation:
379383
"Specify which validation steps TypeDoc should perform on your generated documentation",
380384

Diff for: src/lib/utils/options/declaration.ts

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ export interface TypeDocOptionMap {
246246
intentionallyNotExported: string[];
247247
validation: ValidationOptions;
248248
requiredToBeDocumented: ReflectionKind.KindString[];
249+
intentionallyNotDocumented: string[];
249250

250251
// Other
251252
watch: boolean;

Diff for: src/lib/utils/options/sources/typedoc.ts

+6
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,12 @@ export function addTypeDocOptions(options: Pick<Options, "addDeclaration">) {
978978
},
979979
defaultValue: OptionDefaults.requiredToBeDocumented,
980980
});
981+
options.addDeclaration({
982+
name: "intentionallyNotDocumented",
983+
help: (i18n) => i18n.help_intentionallyNotDocumented(),
984+
type: ParameterType.Array,
985+
defaultValue: [],
986+
});
981987

982988
options.addDeclaration({
983989
name: "validation",

Diff for: src/lib/validation/documentation.ts

+21
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function validateDocumentation(
1313
project: ProjectReflection,
1414
logger: Logger,
1515
requiredToBeDocumented: readonly ReflectionKind.KindString[],
16+
intentionallyNotDocumented: readonly string[],
1617
): void {
1718
let kinds = requiredToBeDocumented.reduce(
1819
(prev, cur) => prev | ReflectionKind[cur],
@@ -37,6 +38,7 @@ export function validateDocumentation(
3738

3839
const toProcess = project.getReflectionsByKind(kinds);
3940
const seen = new Set<Reflection>();
41+
const intentionalUsage = new Set<number>();
4042

4143
outer: while (toProcess.length) {
4244
const ref = toProcess.shift()!;
@@ -111,6 +113,14 @@ export function validateDocumentation(
111113
continue;
112114
}
113115

116+
const intentionalIndex = intentionallyNotDocumented.indexOf(
117+
ref.getFriendlyFullName(),
118+
);
119+
if (intentionalIndex !== -1) {
120+
intentionalUsage.add(intentionalIndex);
121+
continue;
122+
}
123+
114124
logger.warn(
115125
logger.i18n.reflection_0_kind_1_defined_in_2_does_not_have_any_documentation(
116126
ref.getFriendlyFullName(),
@@ -120,4 +130,15 @@ export function validateDocumentation(
120130
);
121131
}
122132
}
133+
134+
const unusedIntentional = intentionallyNotDocumented.filter(
135+
(_, i) => !intentionalUsage.has(i),
136+
);
137+
if (unusedIntentional.length) {
138+
logger.warn(
139+
logger.i18n.invalid_intentionally_not_documented_names_0(
140+
unusedIntentional.join("\n\t"),
141+
),
142+
);
143+
}
123144
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/** Foo doc */
2+
export interface Foo {
3+
notDoc: string;
4+
notDoc2: string;
5+
}

Diff for: src/test/validation.test.ts

+23-5
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ describe("validateDocumentation", () => {
156156
it("Should correctly handle functions", () => {
157157
const project = convertValidationFile("function.ts");
158158
const logger = new TestLogger();
159-
validateDocumentation(project, logger, ["Function"]);
159+
validateDocumentation(project, logger, ["Function"], []);
160160

161161
logger.expectMessage(
162162
"warn: bar (CallSignature), defined in */function.ts, does not have any documentation",
@@ -167,7 +167,7 @@ describe("validateDocumentation", () => {
167167
it("Should correctly handle accessors", () => {
168168
const project = convertValidationFile("getSignature.ts");
169169
const logger = new TestLogger();
170-
validateDocumentation(project, logger, ["Accessor"]);
170+
validateDocumentation(project, logger, ["Accessor"], []);
171171

172172
logger.expectMessage(
173173
"warn: Foo.foo (GetSignature), defined in */getSignature.ts, does not have any documentation",
@@ -178,7 +178,7 @@ describe("validateDocumentation", () => {
178178
it("Should correctly handle constructors", () => {
179179
const project = convertValidationFile("class.ts");
180180
const logger = new TestLogger();
181-
validateDocumentation(project, logger, ["Constructor"]);
181+
validateDocumentation(project, logger, ["Constructor"], []);
182182

183183
logger.expectMessage(
184184
"warn: Foo.constructor (ConstructorSignature), defined in */class.ts, does not have any documentation",
@@ -189,7 +189,7 @@ describe("validateDocumentation", () => {
189189
it("Should correctly handle interfaces", () => {
190190
const project = convertValidationFile("interface.ts");
191191
const logger = new TestLogger();
192-
validateDocumentation(project, logger, ["Method"]);
192+
validateDocumentation(project, logger, ["Method"], []);
193193

194194
logger.expectMessage(
195195
"warn: Foo.method (CallSignature), defined in */interface.ts, does not have any documentation",
@@ -200,8 +200,26 @@ describe("validateDocumentation", () => {
200200
it("Should correctly handle callback parameters", () => {
201201
const project = convertValidationFile("callbackParameters.ts");
202202
const logger = new TestLogger();
203-
validateDocumentation(project, logger, ["Parameter", "Property"]);
203+
validateDocumentation(project, logger, ["Parameter", "Property"], []);
204204

205205
logger.expectNoOtherMessages();
206206
});
207+
208+
it("#2863 supports intentionallyNotDocumented", () => {
209+
const project = convertValidationFile("intentionallyNotDocumented.ts");
210+
211+
const logger = new TestLogger();
212+
validateDocumentation(
213+
project,
214+
logger,
215+
["Property"],
216+
["Foo.notDoc", "Foo.doesNotExist"],
217+
);
218+
219+
logger.expectMessage(
220+
"warn: Foo.notDoc2 * does not have any documentation",
221+
);
222+
logger.expectMessage("warn: The following qualified*Foo.doesNotExist");
223+
logger.expectNoOtherMessages();
224+
});
207225
});

0 commit comments

Comments
 (0)