|
1 |
| -import { schema, cfnLintAnnotations } from '@aws-cdk/cfnspec'; |
| 1 | +import { schema, cfnLintAnnotations, typeDocs } from '@aws-cdk/cfnspec'; |
2 | 2 | import { CodeMaker } from 'codemaker';
|
3 | 3 | import * as genspec from './genspec';
|
4 | 4 | import { itemTypeNames, PropertyAttributeName, scalarTypeNames, SpecName } from './spec-utils';
|
@@ -115,7 +115,7 @@ export default class CodeGenerator {
|
115 | 115 | const name = genspec.CodeName.forResourceProperties(resourceContext);
|
116 | 116 |
|
117 | 117 | this.docLink(spec.Documentation,
|
118 |
| - `Properties for defining a \`${resourceContext.specName!.fqn}\``, |
| 118 | + `Properties for defining a \`${resourceContext.className}\``, |
119 | 119 | '',
|
120 | 120 | '@stability external');
|
121 | 121 | this.code.openBlock(`export interface ${name.className}`);
|
@@ -144,15 +144,17 @@ export default class CodeGenerator {
|
144 | 144 | container: Container): Dictionary<string> {
|
145 | 145 | const propertyMap: Dictionary<string> = {};
|
146 | 146 |
|
| 147 | + const docs = typeDocs(resource.specName?.fqn ?? ''); |
| 148 | + |
147 | 149 | Object.keys(propertiesSpec).sort(propertyComparator).forEach(propName => {
|
148 | 150 | this.code.line();
|
149 | 151 | const propSpec = propertiesSpec[propName];
|
150 |
| - const additionalDocs = resource.specName!.relativeName(propName).fqn; |
| 152 | + const additionalDocs = docs.properties[propName] || quoteCode(resource.specName!.relativeName(propName).fqn); |
151 | 153 | const newName = this.emitProperty({
|
152 | 154 | context: resource,
|
153 | 155 | propName,
|
154 | 156 | spec: propSpec,
|
155 |
| - additionalDocs: quoteCode(additionalDocs), |
| 157 | + additionalDocs, |
156 | 158 | },
|
157 | 159 | container,
|
158 | 160 | );
|
@@ -192,15 +194,20 @@ export default class CodeGenerator {
|
192 | 194 | this.code.line();
|
193 | 195 | }
|
194 | 196 |
|
| 197 | + const docs = typeDocs(cfnName); |
| 198 | + |
195 | 199 | //
|
196 | 200 | // The class declaration representing this Resource
|
197 | 201 | //
|
198 | 202 |
|
199 |
| - this.docLink(spec.Documentation, |
| 203 | + this.docLink(spec.Documentation, ...[ |
200 | 204 | `A CloudFormation \`${cfnName}\``,
|
201 | 205 | '',
|
| 206 | + ...docs.description.split('\n'), |
| 207 | + '', |
202 | 208 | `@cloudformationResource ${cfnName}`,
|
203 |
| - '@stability external'); |
| 209 | + '@stability external', |
| 210 | + ]); |
204 | 211 | this.openClass(resourceName, RESOURCE_BASE_CLASS);
|
205 | 212 |
|
206 | 213 | //
|
@@ -271,7 +278,9 @@ export default class CodeGenerator {
|
271 | 278 |
|
272 | 279 | this.code.line();
|
273 | 280 |
|
274 |
| - this.docLink(undefined, `@cloudformationAttribute ${attributeName}`); |
| 281 | + this.docLink(undefined, |
| 282 | + docs.attributes?.[attributeName] ?? '', |
| 283 | + `@cloudformationAttribute ${attributeName}`); |
275 | 284 | const attr = genspec.attributeDefinition(attributeName, attributeSpec);
|
276 | 285 |
|
277 | 286 | this.code.line(`public readonly ${attr.propertyName}: ${attr.attributeType};`);
|
@@ -847,18 +856,25 @@ export default class CodeGenerator {
|
847 | 856 | this.code.line();
|
848 | 857 | this.beginNamespace(typeName);
|
849 | 858 |
|
850 |
| - this.docLink(propTypeSpec.Documentation, '@stability external'); |
| 859 | + const docs = typeDocs(resourceContext.specName?.fqn ?? '', (typeName.specName as PropertyAttributeName | undefined)?.propAttrName); |
| 860 | + |
| 861 | + this.docLink( |
| 862 | + propTypeSpec.Documentation, |
| 863 | + docs.description, |
| 864 | + '@stability external', |
| 865 | + ); |
851 | 866 | /*
|
852 | 867 | if (!propTypeSpec.Properties || Object.keys(propTypeSpec.Properties).length === 0) {
|
853 | 868 | this.code.line('// eslint-disable-next-line somethingsomething | A genuine empty-object type');
|
854 | 869 | }
|
855 | 870 | */
|
856 | 871 | this.code.openBlock(`export interface ${typeName.className}`);
|
857 | 872 | const conversionTable: Dictionary<string> = {};
|
| 873 | + |
858 | 874 | if (propTypeSpec.Properties) {
|
859 | 875 | Object.keys(propTypeSpec.Properties).forEach(propName => {
|
860 | 876 | const propSpec = propTypeSpec.Properties[propName];
|
861 |
| - const additionalDocs = quoteCode(`${typeName.fqn}.${propName}`); |
| 877 | + const additionalDocs = docs.properties[propName] || quoteCode(`${typeName.fqn}.${propName}`); |
862 | 878 | const newName = this.emitInterfaceProperty({
|
863 | 879 | context: resourceContext,
|
864 | 880 | propName,
|
@@ -950,12 +966,37 @@ export default class CodeGenerator {
|
950 | 966 | private docLink(link: string | undefined, ...before: string[]): void {
|
951 | 967 | if (!link && before.length === 0) { return; }
|
952 | 968 | this.code.line('/**');
|
953 |
| - before.forEach(line => this.code.line(` * ${line}`.trimRight())); |
| 969 | + before.flatMap(x => x.split('\n')).forEach(line => this.code.line(` * ${escapeDocText(line)}`.trimRight())); |
954 | 970 | if (link) {
|
| 971 | + if (before.length > 0) { |
| 972 | + this.code.line(' *'); |
| 973 | + } |
955 | 974 | this.code.line(` * @link ${link}`);
|
956 | 975 | }
|
957 | 976 | this.code.line(' */');
|
958 |
| - return; |
| 977 | + |
| 978 | + /** |
| 979 | + * Add escapes to the doc text to avoid text that breaks the parsing of the string |
| 980 | + * |
| 981 | + * We currently escape the following sequences: |
| 982 | + * |
| 983 | + * - <asterisk><slash> (* /): if this occurs somewhere in the doc text, it |
| 984 | + * will end the block comment in the wrong place. Break up those |
| 985 | + * characters by inserting a space. Would have loved to use a zero-width space, |
| 986 | + * but I'm very very afraid it will break codegen in subtle ways, and just using |
| 987 | + * a space feels safer. |
| 988 | + * - \u: if this occurs in Java code, the Java compiler will try and parse the |
| 989 | + * following 4 characters as a unicode code point, and fail if the 4 characters |
| 990 | + * aren't hex digits. This is formally a bug in pacmak (it should do the escaping |
| 991 | + * while rendering, https://github.com/aws/jsii/issues/3302), but to |
| 992 | + * expedite the build fixing it here as well. Replace with '\ u' (tried using |
| 993 | + * `\\u` but for some reason that also doesn't carry over to codegen). |
| 994 | + */ |
| 995 | + function escapeDocText(x: string) { |
| 996 | + x = x.replace(/\*\//g, '* /'); |
| 997 | + x = x.replace(/\\u/g, '\\ u'); |
| 998 | + return x; |
| 999 | + } |
959 | 1000 | }
|
960 | 1001 | }
|
961 | 1002 |
|
|
0 commit comments