Skip to content

Commit 7417b70

Browse files
committed
Add unit tests for include/includeCode with regions
1 parent 82c6084 commit 7417b70

File tree

18 files changed

+280
-32
lines changed

18 files changed

+280
-32
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ title: Changelog
1515
- Fixed an issue where TypeDoc would incorrectly ignore type arguments in references, #2823.
1616
- Improved narrator support for labeling icons, #2832.
1717

18+
### Thanks!
19+
20+
- @shawninder
21+
1822
## v0.27.6 (2024-12-26)
1923

2024
### Features

site/options/comments.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,7 @@ Also see [`blockTags`](#blocktags) and [`inlineTags`](#inlinetags).
185185
```
186186

187187
Specifies modifier tags which should be copied to all children of the parent reflection.
188-
189-
> [!note]
190-
> `@deprecated` is a block tag, not a modifier tag, so should not be specified here.
188+
Note that `@deprecated` is a block tag, not a modifier tag, so should not be specified here.
191189

192190
## excludeTags
193191

src/lib/converter/plugins/IncludePlugin.ts

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export class IncludePlugin extends ConverterComponent {
9090
part.text,
9191
text,
9292
target,
93+
part.tag,
9394
)
9495
: requestedLines
9596
? this.getLines(
@@ -98,6 +99,7 @@ export class IncludePlugin extends ConverterComponent {
9899
part.text,
99100
text,
100101
requestedLines,
102+
part.tag,
101103
)
102104
: text,
103105
file,
@@ -126,6 +128,7 @@ export class IncludePlugin extends ConverterComponent {
126128
part.text,
127129
text,
128130
target,
131+
part.tag,
129132
)
130133
: requestedLines
131134
? this.getLines(
@@ -134,13 +137,14 @@ export class IncludePlugin extends ConverterComponent {
134137
part.text,
135138
text,
136139
requestedLines,
140+
part.tag,
137141
)
138142
: text,
139143
),
140144
};
141145
}
142146
} else {
143-
this.logger.warn(
147+
this.logger.error(
144148
this.logger.i18n.include_0_in_1_specified_2_resolved_to_3_does_not_exist(
145149
part.tag,
146150
refl.getFriendlyFullName(),
@@ -159,8 +163,20 @@ export class IncludePlugin extends ConverterComponent {
159163
textPart: string,
160164
text: string,
161165
target: string,
166+
tag: string,
162167
) {
163168
const regionTagsList = regionTagREsByExt[ext];
169+
if (!regionTagsList) {
170+
this.logger.error(
171+
this.logger.i18n.include_0_tag_in_1_region_2_region_not_supported(
172+
tag,
173+
refl.getFriendlyFullName(),
174+
textPart,
175+
),
176+
);
177+
return "";
178+
}
179+
164180
let found: string | false = false;
165181
for (const [startTag, endTag] of regionTagsList) {
166182
const safeTarget = escapeRegExp(target);
@@ -171,7 +187,8 @@ export class IncludePlugin extends ConverterComponent {
171187
const foundEnd = end && end.length > 0;
172188
if (foundStart && !foundEnd) {
173189
this.logger.error(
174-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_close_not_found(
190+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_close_not_found(
191+
tag,
175192
refl.getFriendlyFullName(),
176193
textPart,
177194
file,
@@ -182,7 +199,8 @@ export class IncludePlugin extends ConverterComponent {
182199
}
183200
if (!foundStart && foundEnd) {
184201
this.logger.error(
185-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_open_not_found(
202+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_open_not_found(
203+
tag,
186204
refl.getFriendlyFullName(),
187205
textPart,
188206
file,
@@ -194,7 +212,8 @@ export class IncludePlugin extends ConverterComponent {
194212
if (foundStart && foundEnd) {
195213
if (start.length > 1) {
196214
this.logger.error(
197-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_open_found_multiple_times(
215+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_open_found_multiple_times(
216+
tag,
198217
refl.getFriendlyFullName(),
199218
textPart,
200219
file,
@@ -205,7 +224,8 @@ export class IncludePlugin extends ConverterComponent {
205224
}
206225
if (end.length > 1) {
207226
this.logger.error(
208-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_close_found_multiple_times(
227+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_close_found_multiple_times(
228+
tag,
209229
refl.getFriendlyFullName(),
210230
textPart,
211231
file,
@@ -216,7 +236,8 @@ export class IncludePlugin extends ConverterComponent {
216236
}
217237
if (found) {
218238
this.logger.error(
219-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_found_multiple_times(
239+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_found_multiple_times(
240+
tag,
220241
refl.getFriendlyFullName(),
221242
textPart,
222243
file,
@@ -231,9 +252,10 @@ export class IncludePlugin extends ConverterComponent {
231252
);
232253
}
233254
}
234-
if (!found) {
255+
if (found === false) {
235256
this.logger.error(
236-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_not_found(
257+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_not_found(
258+
tag,
237259
refl.getFriendlyFullName(),
238260
textPart,
239261
file,
@@ -244,7 +266,8 @@ export class IncludePlugin extends ConverterComponent {
244266
}
245267
if (found.trim() === "") {
246268
this.logger.warn(
247-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_region_3_region_empty(
269+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_empty(
270+
tag,
248271
refl.getFriendlyFullName(),
249272
textPart,
250273
file,
@@ -261,6 +284,7 @@ export class IncludePlugin extends ConverterComponent {
261284
textPart: string,
262285
text: string,
263286
requestedLines: string,
287+
tag: string,
264288
) {
265289
let output = "";
266290
const lines = text.split(/\r\n|\r|\n/);
@@ -269,7 +293,8 @@ export class IncludePlugin extends ConverterComponent {
269293
const [start, end] = requestedLineString.split("-").map(Number);
270294
if (start > end) {
271295
this.logger.error(
272-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_lines_3_invalid_range(
296+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_invalid_range(
297+
tag,
273298
refl.getFriendlyFullName(),
274299
textPart,
275300
file,
@@ -280,7 +305,8 @@ export class IncludePlugin extends ConverterComponent {
280305
}
281306
if (start > lines.length || end > lines.length) {
282307
this.logger.error(
283-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_lines_3_but_only_4_lines(
308+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines(
309+
tag,
284310
refl.getFriendlyFullName(),
285311
textPart,
286312
file,
@@ -295,7 +321,8 @@ export class IncludePlugin extends ConverterComponent {
295321
const requestedLine = Number(requestedLineString);
296322
if (requestedLine > lines.length) {
297323
this.logger.error(
298-
this.logger.i18n.includeCode_tag_in_0_specified_1_file_2_lines_3_but_only_4_lines(
324+
this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines(
325+
tag,
299326
refl.getFriendlyFullName(),
300327
textPart,
301328
file,
@@ -312,6 +339,7 @@ export class IncludePlugin extends ConverterComponent {
312339
return output;
313340
}
314341
}
342+
315343
function makeCodeBlock(lang: string, code: string) {
316344
const escaped = code.replace(/`(?=`)/g, "`\u200B");
317345
return "\n\n```" + lang + "\n" + escaped.trimEnd() + "\n```";
@@ -397,14 +425,22 @@ const regionTagREsByExt: Record<string, RegionTagRETuple[]> = {
397425
],
398426
],
399427
};
400-
regionTagREsByExt["fs"] = regionTagREsByExt["ts"].concat([
401-
(regionName) => new RegExp(`(#_region) *${regionName} *\n`, "g"),
402-
(regionName) => new RegExp(`(#_endregion) *${regionName} *\n`, "g"),
403-
]);
404-
regionTagREsByExt["java"] = regionTagREsByExt["ts"].concat([
405-
(regionName) => new RegExp(`// *<editor-fold> *${regionName} *\n`, "g"),
406-
(regionName) => new RegExp(`// *</editor-fold> *${regionName} *\n`, "g"),
407-
]);
428+
regionTagREsByExt["fs"] = [
429+
...regionTagREsByExt["ts"],
430+
[
431+
(regionName) => new RegExp(`(#_region) *${regionName} *\n`, "g"),
432+
(regionName) => new RegExp(`(#_endregion) *${regionName} *\n`, "g"),
433+
],
434+
];
435+
regionTagREsByExt["java"] = [
436+
...regionTagREsByExt["ts"],
437+
[
438+
(regionName) =>
439+
new RegExp(`// *<editor-fold> *${regionName} *\n`, "g"),
440+
(regionName) =>
441+
new RegExp(`// *</editor-fold> *${regionName} *\n`, "g"),
442+
],
443+
];
408444
regionTagREsByExt["cpp"] = regionTagREsByExt["c"];
409445
regionTagREsByExt["less"] = regionTagREsByExt["css"];
410446
regionTagREsByExt["scss"] = regionTagREsByExt["css"];

src/lib/internationalization/locales/en.cts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,16 @@ export = {
119119

120120
include_0_in_1_specified_2_resolved_to_3_does_not_exist: `{0} tag in comment for {1} specified "{2}" to include, which was resolved to "{3}" and does not exist or is not a file.`,
121121
include_0_in_1_specified_2_circular_include_3: `{0} tag in comment for {1} specified "{2}" to include, which resulted in a circular include:\n\t{3}`,
122-
includeCode_tag_in_0_specified_1_file_2_region_3_region_not_found: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled "{3}", but the region was not found in the file.`,
123-
includeCode_tag_in_0_specified_1_file_2_region_3_region_close_not_found: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled "{3}", but the region closing comment was not found in the file.`,
124-
includeCode_tag_in_0_specified_1_file_2_region_3_region_open_not_found: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled "{3}", but the region opening comment was not found in the file.`,
125-
includeCode_tag_in_0_specified_1_file_2_region_3_region_close_found_multiple_times: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled {3}, but the region closing comment was found multiple times in the file.`,
126-
includeCode_tag_in_0_specified_1_file_2_region_3_region_open_found_multiple_times: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled {3}, but the region opening comment was found multiple times in the file.`,
127-
includeCode_tag_in_0_specified_1_file_2_region_3_region_found_multiple_times: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled {3}, but the region was found multiple times in the file.`,
128-
includeCode_tag_in_0_specified_1_file_2_region_3_region_empty: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the region labeled {3}. The region was found but it is empty or contains only whitespace.`,
129-
includeCode_tag_in_0_specified_1_file_2_lines_3_invalid_range: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the lines {3}, but an invalid range was specified.`,
130-
includeCode_tag_in_0_specified_1_file_2_lines_3_but_only_4_lines: `@includeCode tag in {0} specified "{1}" to include from file "{2}" the lines {3}, but the file only has {4} lines.`,
122+
include_0_tag_in_1_specified_2_file_3_region_4_region_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region was not found in the file.`,
123+
include_0_tag_in_1_region_2_region_not_supported: `{0} tag in {1} specified "{2}", but regions are not supported for this file extension.`,
124+
include_0_tag_in_1_specified_2_file_3_region_4_region_close_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region closing comment was not found in the file.`,
125+
include_0_tag_in_1_specified_2_file_3_region_4_region_open_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region opening comment was not found in the file.`,
126+
include_0_tag_in_1_specified_2_file_3_region_4_region_close_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region closing comment was found multiple times in the file.`,
127+
include_0_tag_in_1_specified_2_file_3_region_4_region_open_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region opening comment was found multiple times in the file.`,
128+
include_0_tag_in_1_specified_2_file_3_region_4_region_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region was found multiple times in the file.`,
129+
include_0_tag_in_1_specified_2_file_3_region_4_region_empty: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}. The region was found but it is empty or contains only whitespace.`,
130+
include_0_tag_in_1_specified_2_file_3_lines_4_invalid_range: `{0} tag in {1} specified "{2}" to include from file "{3}" the lines {4}, but an invalid range was specified.`,
131+
include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines: `{0} tag in {1} specified "{2}" to include from file "{3}" the lines {4}, but the file only has {5} lines.`,
131132

132133
// output plugins
133134
custom_css_file_0_does_not_exist: `Custom CSS file at {0} does not exist`,

src/lib/internationalization/translatable.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type TranslationConstraint = [
4747
BuildConstraint<0 | 1>,
4848
BuildConstraint<0 | 1 | 2>,
4949
BuildConstraint<0 | 1 | 2 | 3>,
50+
BuildConstraint<0 | 1 | 2 | 3 | 4>,
5051
];
5152

5253
// Compiler errors here which says a property is missing indicates that the value on translatable

src/test/behavior.c2.test.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,4 +1306,114 @@ describe("Behavior Tests", () => {
13061306
'warn: The signature fn3 has an @param with name "options.c", which was not used',
13071307
);
13081308
});
1309+
1310+
it("@includeCode handles regions", () => {
1311+
const project = convert("includeTag/includeTag");
1312+
const code = getComment(project, "region");
1313+
equal(code, "\n\n```ts\nexport const a = 123;\n```");
1314+
});
1315+
1316+
it("@includeCode handles line numbers", () => {
1317+
const project = convert("includeTag/includeTag");
1318+
const code = getComment(project, "line");
1319+
equal(code, "\n\n```ts\nexport const a = 123;\n```");
1320+
});
1321+
1322+
it("@include handles line numbers", () => {
1323+
const project = convert("includeTag/includeTag");
1324+
const code = getComment(project, "lineText");
1325+
equal(code, "Line 3");
1326+
});
1327+
1328+
it("@include handles full files", () => {
1329+
const project = convert("includeTag/includeTag");
1330+
const code = getComment(project, "fullFile");
1331+
equal(code, "Unknown extension doesn't support regions");
1332+
});
1333+
1334+
it("@include works within documents", () => {
1335+
const project = convert("includeTag/includeTag");
1336+
const doc = project.getChildByName(["includeInDoc"]);
1337+
ok(doc?.isDocument());
1338+
equal(
1339+
Comment.combineDisplayParts(doc.content),
1340+
"\n\n```md\n{@includeCode includeInDoc.md}\n```",
1341+
);
1342+
});
1343+
1344+
it("@includeCode warns about missing regions", () => {
1345+
convert("includeTag/missingRegion");
1346+
1347+
logger.expectMessage(
1348+
"error: @includeCode *noRegion* the region was not found in the file.",
1349+
);
1350+
1351+
logger.expectMessage(
1352+
"error: @includeCode *missingStart* the region opening comment was not found in the file.",
1353+
);
1354+
1355+
logger.expectMessage(
1356+
"error: @includeCode *missingEnd* the region closing comment was not found in the file.",
1357+
);
1358+
});
1359+
1360+
it("@includeCode warns about duplicate regions", () => {
1361+
convert("includeTag/duplicateRegion");
1362+
1363+
logger.expectMessage(
1364+
"error: @includeCode *dupStart* the region opening comment was found multiple times in the file.",
1365+
);
1366+
1367+
logger.expectMessage(
1368+
"error: @includeCode *dupEnd* the region closing comment was found multiple times in the file.",
1369+
);
1370+
1371+
logger.expectMessage(
1372+
"error: @includeCode *#dup* the region was found multiple times in the file.",
1373+
);
1374+
});
1375+
1376+
it("@includeCode warns about invalid line ranges", () => {
1377+
convert("includeTag/invalidLineRanges");
1378+
1379+
logger.expectMessage(
1380+
'error: @includeCode *:100-200" * the file only has*',
1381+
);
1382+
1383+
logger.expectMessage(
1384+
'error: @includeCode *:200-100" * an invalid range was specified.',
1385+
);
1386+
1387+
logger.expectMessage('error: @includeCode *:300" * the file only has*');
1388+
});
1389+
1390+
it("@includeCode warns about empty region", () => {
1391+
convert("includeTag/emptyRegion");
1392+
1393+
logger.expectMessage("warn: @includeCode *found but it is empty*");
1394+
});
1395+
1396+
it("@includeCode warns about unsupported region", () => {
1397+
convert("includeTag/unsupportedExtension");
1398+
1399+
logger.expectMessage(
1400+
"error: @includeCode * regions are not supported for this file extension.",
1401+
);
1402+
});
1403+
1404+
it("@includeCode warns about invalid file references", () => {
1405+
convert("includeTag/invalidInclude");
1406+
1407+
logger.expectMessage(
1408+
"error: @includeCode *doesNotExist.txt* does not exist or is not a file.",
1409+
);
1410+
});
1411+
1412+
it("@include warns about circular references", () => {
1413+
convert("includeTag/circularInclude");
1414+
1415+
logger.expectMessage(
1416+
"error: @include *#circular* resulted in a circular include:*",
1417+
);
1418+
});
13091419
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* {@include includeTag.md#circular}
3+
*/
4+
export const circular = true;

0 commit comments

Comments
 (0)