Skip to content

Commit c6c66e9

Browse files
authored
feat(cfn2ts): make cfn2ts output TSDoc-compatible docblocks (#2000)
Change our Sphinx output to MarkDown output, change attributes to styles that can be parsed by TSDoc.
1 parent 6afa87f commit c6c66e9

File tree

2 files changed

+27
-21
lines changed

2 files changed

+27
-21
lines changed

tools/awslint/lib/cfn-resources.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function findCfnResources(assembly: reflect.Assembly): CfnResourceSpec[]
4040

4141
// HACK: extract full CFN name from initializer docs
4242
const initializerDoc = (layer1.initializer && layer1.initializer.docs.docs.comment) || '';
43-
const out = /Creates a new ``([^`]+)``/.exec(initializerDoc);
43+
const out = /a new `([^`]+)`/.exec(initializerDoc);
4444
const fullname = out && out[1];
4545
if (!fullname) {
4646
throw new Error('Unable to extract CloudFormation resource name from initializer documentation');

tools/cfn2ts/lib/codegen.ts

+26-20
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,8 @@ export default class CodeGenerator {
104104
}
105105
}
106106

107-
private openClass(name: genspec.CodeName, docLink?: string, superClasses?: string, deprecation?: string) {
107+
private openClass(name: genspec.CodeName, superClasses?: string) {
108108
const extendsPostfix = superClasses ? ` extends ${superClasses}` : '';
109-
const before = deprecation ? [ `@deprecated ${deprecation}` ] : [ ];
110-
this.docLink(docLink, ...before);
111109
this.code.openBlock(`export class ${name.className}${extendsPostfix}`);
112110
return name.className;
113111
}
@@ -120,7 +118,7 @@ export default class CodeGenerator {
120118
if (!spec.Properties || Object.keys(spec.Properties).length === 0) { return; }
121119
const name = genspec.CodeName.forResourceProperties(resourceContext);
122120

123-
this.docLink(spec.Documentation);
121+
this.docLink(spec.Documentation, `Properties for defining a \`${resourceContext.specName!.fqn}\``);
124122
this.code.openBlock(`export interface ${name.className}`);
125123

126124
const conversionTable = this.emitPropsTypeProperties(resourceContext, spec.Properties);
@@ -172,6 +170,8 @@ export default class CodeGenerator {
172170
private emitResourceType(resourceName: genspec.CodeName, spec: schema.ResourceType, deprecated?: genspec.CodeName): void {
173171
this.beginNamespace(resourceName);
174172

173+
const cfnName = resourceName.specName!.fqn;
174+
175175
//
176176
// Props Bag for this Resource
177177
//
@@ -185,21 +185,27 @@ export default class CodeGenerator {
185185
`"cloudformation.${resourceName.fqn}" will be deprecated in a future release ` +
186186
`in favor of "${deprecated.fqn}" (see https://github.com/awslabs/aws-cdk/issues/878)`;
187187

188-
this.openClass(resourceName, spec.Documentation, RESOURCE_BASE_CLASS, deprecation);
188+
this.docLink(spec.Documentation, ...[
189+
`A CloudFormation \`${cfnName}\``,
190+
'',
191+
`@cloudformationResource ${cfnName}`,
192+
...(deprecation ? [ `@deprecated ${deprecation}` ] : [ ]),
193+
]);
194+
this.openClass(resourceName, RESOURCE_BASE_CLASS);
189195

190196
//
191197
// Static inspectors.
192198
//
193199

194-
const resourceTypeName = `${JSON.stringify(resourceName.specName!.fqn)}`;
200+
const resourceTypeName = `${JSON.stringify(cfnName)}`;
195201
this.code.line('/**');
196202
this.code.line(` * The CloudFormation resource type name for this resource class.`);
197203
this.code.line(' */');
198204
this.code.line(`public static readonly resourceTypeName = ${resourceTypeName};`);
199205

200206
if (spec.RequiredTransform) {
201207
this.code.line('/**');
202-
this.code.line(' * The ``Transform`` a template must use in order to use this resource');
208+
this.code.line(' * The `Transform` a template must use in order to use this resource');
203209
this.code.line(' */');
204210
this.code.line(`public static readonly requiredTransform = ${JSON.stringify(spec.RequiredTransform)};`);
205211
}
@@ -216,7 +222,7 @@ export default class CodeGenerator {
216222

217223
this.code.line();
218224

219-
this.docLink(undefined, `@cloudformation_attribute ${attributeName}`);
225+
this.docLink(undefined, `@cloudformationAttribute ${attributeName}`);
220226
const attr = genspec.attributeDefinition(resourceName, attributeName, attributeSpec);
221227

222228
this.code.line(`public readonly ${attr.propertyName}: ${attr.attributeType};`);
@@ -242,11 +248,11 @@ export default class CodeGenerator {
242248
if (tagEnum !== `${TAG_TYPE}.NotTaggable`) {
243249
this.code.line();
244250
this.code.line('/**');
245-
this.code.line(' * The ``TagManager`` handles setting, removing and formatting tags');
251+
this.code.line(' * The `TagManager` handles setting, removing and formatting tags');
246252
this.code.line(' *');
247253
this.code.line(' * Tags should be managed either passing them as properties during');
248254
this.code.line(' * initiation or by calling methods on this object. If both techniques are');
249-
this.code.line(' * used only the tags from the TagManager will be used. ``Tag`` (aspect)');
255+
this.code.line(' * used only the tags from the TagManager will be used. `Tag` (aspect)');
250256
this.code.line(' * will use the manager.');
251257
this.code.line(' */');
252258
this.code.line(`public readonly tags = new ${TAG_MANAGER}(${tagEnum}, ${resourceTypeName});`);
@@ -258,11 +264,11 @@ export default class CodeGenerator {
258264

259265
this.code.line();
260266
this.code.line('/**');
261-
this.code.line(` * Creates a new ${quoteCode(resourceName.specName!.fqn)}.`);
267+
this.code.line(` * Create a new ${quoteCode(resourceName.specName!.fqn)}.`);
262268
this.code.line(' *');
263-
this.code.line(` * @param scope scope in which this resource is defined`);
264-
this.code.line(` * @param id scoped id of the resource`);
265-
this.code.line(` * @param props resource properties`);
269+
this.code.line(` * @param scope - scope in which this resource is defined`);
270+
this.code.line(` * @param id - scoped id of the resource`);
271+
this.code.line(` * @param props - resource properties`);
266272
this.code.line(' */');
267273
const optionalProps = spec.Properties && !Object.values(spec.Properties).some(p => p.Required || false);
268274
const propsArgument = propsType ? `, props${optionalProps ? '?' : ''}: ${propsType.className}` : '';
@@ -362,7 +368,7 @@ export default class CodeGenerator {
362368
this.code.line('/**');
363369
this.code.line(` * Renders the AWS CloudFormation properties of an ${quoteCode(typeName.specName!.fqn)} resource`);
364370
this.code.line(' *');
365-
this.code.line(` * @param properties the TypeScript properties of a ${quoteCode(typeName.className)}`);
371+
this.code.line(` * @param properties - the TypeScript properties of a ${quoteCode(typeName.className)}`);
366372
this.code.line(' *');
367373
this.code.line(` * @returns the AWS CloudFormation properties of an ${quoteCode(typeName.specName!.fqn)} resource.`);
368374
this.code.line(' */');
@@ -448,7 +454,7 @@ export default class CodeGenerator {
448454
this.code.line('/**');
449455
this.code.line(` * Determine whether the given properties match those of a ${quoteCode(typeName.className)}`);
450456
this.code.line(' *');
451-
this.code.line(` * @param properties the TypeScript properties of a ${quoteCode(typeName.className)}`);
457+
this.code.line(` * @param properties - the TypeScript properties of a ${quoteCode(typeName.className)}`);
452458
this.code.line(' *');
453459
this.code.line(' * @returns the result of the validation.');
454460
this.code.line(' */');
@@ -622,9 +628,9 @@ export default class CodeGenerator {
622628
private docLink(link: string | undefined, ...before: string[]) {
623629
if (!link && before.length === 0) { return; }
624630
this.code.line('/**');
625-
before.forEach(line => this.code.line(` * ${line}`));
631+
before.forEach(line => this.code.line(` * ${line}`.trimRight()));
626632
if (link) {
627-
this.code.line(` * @link ${link}`);
633+
this.code.line(` * @see ${link}`);
628634
}
629635
this.code.line(' */');
630636
return;
@@ -639,14 +645,14 @@ export default class CodeGenerator {
639645

640646
/**
641647
* Quotes a code name for inclusion in a JSDoc comment, so it will render properly
642-
* in the Sphinx output.
648+
* in the Markdown output.
643649
*
644650
* @param code a code name to be quoted.
645651
*
646652
* @returns the code name surrounded by double backticks.
647653
*/
648654
function quoteCode(code: string): string {
649-
return '``' + code + '``';
655+
return '`' + code + '`';
650656
}
651657

652658
function tokenizableType(alternatives: string[]) {

0 commit comments

Comments
 (0)