Skip to content

Commit dbbf5df

Browse files
committed
Add TSDocConfigFile.loadFromObject() needed for microsoft/rushstack#1950
1 parent bab6753 commit dbbf5df

File tree

2 files changed

+110
-9
lines changed

2 files changed

+110
-9
lines changed

tsdoc-config/src/TSDocConfigFile.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export class TSDocConfigFile {
9494
}
9595

9696
/**
97-
* The full path of the file that was attempted to load.
97+
* The full path of the file that was attempted to load, or an empty string if the configuration was
98+
* loaded from a source that is not a file.
9899
*/
99100
public get filePath(): string {
100101
return this._filePath;
@@ -276,13 +277,9 @@ export class TSDocConfigFile {
276277
this._hasErrors = true;
277278
}
278279

279-
private _loadJsonFile(): void {
280-
const configJsonContent: string = fs.readFileSync(this._filePath).toString();
281-
this._fileMTime = fs.statSync(this._filePath).mtimeMs;
280+
private _loadJsonObject(configJson: IConfigJson): void {
282281
this._fileNotFound = false;
283282

284-
const configJson: IConfigJson = jju.parse(configJsonContent, { mode: 'cjson' });
285-
286283
if (configJson.$schema !== TSDocConfigFile.CURRENT_SCHEMA_URL) {
287284
this._reportError({
288285
messageId: TSDocMessageId.ConfigFileUnsupportedSchema,
@@ -381,7 +378,12 @@ export class TSDocConfigFile {
381378
}
382379
alreadyVisitedPaths.add(hashKey);
383380

384-
this._loadJsonFile();
381+
const configJsonContent: string = fs.readFileSync(this._filePath).toString();
382+
this._fileMTime = fs.statSync(this._filePath).mtimeMs;
383+
384+
const configJson: IConfigJson = jju.parse(configJsonContent, { mode: 'cjson' });
385+
386+
this._loadJsonObject(configJson);
385387

386388
const configFileFolder: string = path.dirname(this.filePath);
387389

@@ -462,6 +464,24 @@ export class TSDocConfigFile {
462464
return configFile;
463465
}
464466

467+
/**
468+
* Loads the object state from a JSON-serializable object as produced by {@link TSDocConfigFile.saveToObject}.
469+
*
470+
* @remarks
471+
* The serialized object has the same structure as `tsdoc.json`; however the `"extends"` field is not allowed.
472+
*/
473+
public static loadFromObject(jsonObject: unknown): TSDocConfigFile {
474+
const configFile: TSDocConfigFile = new TSDocConfigFile();
475+
476+
configFile._loadJsonObject(jsonObject as IConfigJson);
477+
478+
if (configFile.extendsPaths.length > 0) {
479+
throw new Error('The "extends" field cannot be used with TSDocConfigFile.loadFromObject()');
480+
}
481+
482+
return configFile;
483+
}
484+
465485
/**
466486
* Initializes a TSDocConfigFile object using the state from the provided `TSDocConfiguration` object.
467487
*/
@@ -563,7 +583,13 @@ export class TSDocConfigFile {
563583
return 'No errors.';
564584
}
565585

566-
let result: string = `Errors encountered for ${this.filePath}:\n`;
586+
let result: string;
587+
588+
if (this.filePath) {
589+
result = `Errors encountered for ${this.filePath}:\n`;
590+
} else {
591+
result = `Errors encountered when loading TSDoc configuration:\n`;
592+
}
567593

568594
for (const message of this.log.messages) {
569595
result += ` ${message.text}\n`;

tsdoc-config/src/__tests__/TSDocConfigFile.test.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TSDocConfiguration } from '@microsoft/tsdoc';
1+
import { Standardization, TSDocConfiguration, TSDocTagDefinition, TSDocTagSyntaxKind } from '@microsoft/tsdoc';
22
import * as path from 'path';
33

44
import { TSDocConfigFile } from '../TSDocConfigFile';
@@ -207,6 +207,8 @@ test('Load p4', () => {
207207

208208
test('Re-serialize p3', () => {
209209
const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p3'));
210+
expect(configFile.hasErrors).toBe(false);
211+
210212
// This is the data from p3/tsdoc.json, ignoring its "extends" field.
211213
expect(configFile.saveToObject()).toMatchInlineSnapshot(`
212214
Object {
@@ -229,6 +231,8 @@ test('Re-serialize p3 without defaults', () => {
229231
parserConfiguration.clear(true);
230232

231233
const defaultsConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(parserConfiguration);
234+
expect(defaultsConfigFile.hasErrors).toBe(false);
235+
232236
// This is the default configuration created by the TSDocConfigFile constructor.
233237
expect(defaultsConfigFile.saveToObject()).toMatchInlineSnapshot(`
234238
Object {
@@ -238,6 +242,7 @@ test('Re-serialize p3 without defaults', () => {
238242
`);
239243

240244
const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p3'));
245+
expect(configFile.hasErrors).toBe(false);
241246
configFile.noStandardTags = true;
242247
configFile.configureParser(parserConfiguration);
243248

@@ -275,6 +280,8 @@ test('Re-serialize p3 with defaults', () => {
275280
const parserConfiguration: TSDocConfiguration = new TSDocConfiguration();
276281

277282
const defaultsConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(parserConfiguration);
283+
expect(defaultsConfigFile.hasErrors).toBe(false);
284+
278285
// This is the default configuration created by the TSDocConfigFile constructor.
279286
expect(defaultsConfigFile.saveToObject()).toMatchInlineSnapshot(`
280287
Object {
@@ -392,6 +399,7 @@ test('Re-serialize p3 with defaults', () => {
392399
`);
393400

394401
const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p3'));
402+
expect(configFile.hasErrors).toBe(false);
395403
configFile.configureParser(parserConfiguration);
396404

397405
const mergedConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(parserConfiguration);
@@ -532,6 +540,7 @@ test('Re-serialize p3 with defaults', () => {
532540

533541
test('Test noStandardTags for p5', () => {
534542
const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p5'));
543+
expect(configFile.hasErrors).toBe(false);
535544

536545
const configuration: TSDocConfiguration = new TSDocConfiguration();
537546
configFile.configureParser(configuration);
@@ -542,10 +551,76 @@ test('Test noStandardTags for p5', () => {
542551

543552
test('Test noStandardTags for p6', () => {
544553
const configFile: TSDocConfigFile = TSDocConfigFile.loadForFolder(path.join(__dirname, 'assets/p6'));
554+
expect(configFile.hasErrors).toBe(false);
545555

546556
const configuration: TSDocConfiguration = new TSDocConfiguration();
547557
configFile.configureParser(configuration);
548558

549559
// noStandardTags=false because tsdoc.json overrides tsdoc-base1.json
550560
expect(configuration.tagDefinitions.length).toBeGreaterThan(0);
551561
});
562+
563+
test('Test loadFromObject()', () => {
564+
const configuration: TSDocConfiguration = new TSDocConfiguration();
565+
configuration.clear(true);
566+
567+
configuration.addTagDefinitions([
568+
new TSDocTagDefinition({ syntaxKind: TSDocTagSyntaxKind.ModifierTag, tagName: '@tag1' }),
569+
new TSDocTagDefinition({ syntaxKind: TSDocTagSyntaxKind.BlockTag, tagName: '@tag2', allowMultiple: true }),
570+
new TSDocTagDefinition({ syntaxKind: TSDocTagSyntaxKind.InlineTag, tagName: '@tag3', allowMultiple: true }),
571+
]);
572+
573+
configuration.setSupportForTag(configuration.tagDefinitions[0], true);
574+
575+
const configFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(configuration);
576+
expect(configFile.hasErrors).toBe(false);
577+
const jsonObject: unknown = configFile.saveToObject();
578+
579+
const configFile2: TSDocConfigFile = TSDocConfigFile.loadFromObject(jsonObject);
580+
expect(configFile2.hasErrors).toBe(false);
581+
const jsonObject2: unknown = configFile2.saveToObject();
582+
583+
expect(jsonObject2).toMatchInlineSnapshot(`
584+
Object {
585+
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
586+
"noStandardTags": true,
587+
"supportForTags": Object {
588+
"@tag1": true,
589+
},
590+
"tagDefinitions": Array [
591+
Object {
592+
"syntaxKind": "modifier",
593+
"tagName": "@tag1",
594+
},
595+
Object {
596+
"allowMultiple": true,
597+
"syntaxKind": "block",
598+
"tagName": "@tag2",
599+
},
600+
Object {
601+
"allowMultiple": true,
602+
"syntaxKind": "inline",
603+
"tagName": "@tag3",
604+
},
605+
],
606+
}
607+
`);
608+
609+
expect(jsonObject2).toStrictEqual(jsonObject);
610+
});
611+
612+
test('Test loadFromObject() with extends', () => {
613+
const configuration: TSDocConfiguration = new TSDocConfiguration();
614+
configuration.clear(true);
615+
616+
const configFile: TSDocConfigFile = TSDocConfigFile.loadFromParser(configuration);
617+
expect(configFile.hasErrors).toBe(false);
618+
const jsonObject: unknown = configFile.saveToObject();
619+
620+
// eslint-disable-next-line
621+
(jsonObject as any)['extends'] = ['./some-file.json'];
622+
623+
expect(() => {
624+
TSDocConfigFile.loadFromObject(jsonObject);
625+
}).toThrowError('The "extends" field cannot be used with TSDocConfigFile.loadFromObject()');
626+
});

0 commit comments

Comments
 (0)