Skip to content

Commit

Permalink
working with <propName>Prop to avoid collisions
Browse files Browse the repository at this point in the history
special case for tags
  • Loading branch information
moofish32 committed Apr 25, 2019
1 parent 2d44ed7 commit af39691
Showing 1 changed file with 75 additions and 22 deletions.
97 changes: 75 additions & 22 deletions tools/cfn2ts/lib/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export default class CodeGenerator {
this.docLink(spec.Documentation, `Properties for defining a \`${resourceContext.specName!.fqn}\``);
this.code.openBlock(`export interface ${name.className}`);

const conversionTable = this.emitPropsTypeProperties(resourceContext, spec.Properties);
const conversionTable = this.emitPropsTypeProperties(resourceContext, spec.Properties, Container.Interface);

this.code.closeBlock();

Expand All @@ -138,13 +138,24 @@ export default class CodeGenerator {
*
* Return a mapping of { originalName -> newName }.
*/
private emitPropsTypeProperties(resource: genspec.CodeName, propertiesSpec: { [name: string]: schema.Property }): Dictionary<string> {
private emitPropsTypeProperties(
resource: genspec.CodeName,
propertiesSpec: { [name: string]: schema.Property },
container: Container): Dictionary<string> {

const propertyMap: Dictionary<string> = {};

Object.keys(propertiesSpec).sort(propertyComparator).forEach(propName => {
this.code.line();
const propSpec = propertiesSpec[propName];
const additionalDocs = resource.specName!.relativeName(propName).fqn;
const newName = this.emitProperty(resource, propName, propSpec, quoteCode(additionalDocs));
const newName = this.emitProperty({
context: resource,
propName,
spec: propSpec,
additionalDocs: quoteCode(additionalDocs),
container,
});
propertyMap[propName] = newName;
});
return propertyMap;
Expand Down Expand Up @@ -243,19 +254,11 @@ export default class CodeGenerator {
attributes.push(refAttribute);
}
}
// set the TagType to help format tags later
const tagEnum = tagType(spec);
if (tagEnum !== `${TAG_TYPE}.NotTaggable`) {
this.code.line();
this.code.line('/**');
this.code.line(' * The `TagManager` handles setting, removing and formatting tags');
this.code.line(' *');
this.code.line(' * Tags should be managed either passing them as properties during');
this.code.line(' * initiation or by calling methods on this object. If both techniques are');
this.code.line(' * used only the tags from the TagManager will be used. `Tag` (aspect)');
this.code.line(' * will use the manager.');
this.code.line(' */');
this.code.line(`public readonly tags: ${TAG_MANAGER};`);

// set class properties to match CloudFormation Properties spec

if (propsType) {
this.emitPropsTypeProperties(resourceName, spec.Properties!, Container.Class);
}

//
Expand Down Expand Up @@ -308,6 +311,9 @@ export default class CodeGenerator {
if (deprecated) {
this.code.line(`this.node.addWarning('DEPRECATION: ${deprecation}');`);
}

// set the TagType to help format tags later
const tagEnum = tagType(spec);
if (tagEnum !== `${TAG_TYPE}.NotTaggable`) {
this.code.line('const tags = props === undefined ? undefined : props.tags;');
this.code.line(`this.tags = new ${TAG_MANAGER}(${tagEnum}, ${resourceTypeName}, tags);`);
Expand Down Expand Up @@ -514,15 +520,26 @@ export default class CodeGenerator {
this.code.closeBlock();
}

private emitProperty(context: genspec.CodeName, propName: string, spec: schema.Property, additionalDocs: string): string {
const question = spec.Required ? '' : '?';
const javascriptPropertyName = genspec.cloudFormationToScriptName(propName);
private emitProperty(props: EmitPropertyProps): string {
const question = props.spec.Required ? '' : '?';
const javascriptPropertyName = genspec.cloudFormationToScriptName(props.propName);

this.docLink(spec.Documentation, additionalDocs);
this.code.line(`readonly ${javascriptPropertyName}${question}: ${this.findNativeType(context, spec, propName)};`);
this.docLink(props.spec.Documentation, props.additionalDocs);
const line = `: ${this.findNativeType(props.context, props.spec, props.propName)};`;

if (props.container === Container.Interface) {
this.code.line(`readonly ${javascriptPropertyName}${question}${line}`);
}
if (props.container === Container.Class) {
if (props.propName === 'Tags' && schema.isTagProperty(props.spec)) {
this.code.line(`public readonly tags: ${TAG_MANAGER};`);
} else {
this.code.line(`public ${javascriptPropertyName}Prop${line}`);
}
}
return javascriptPropertyName;
}

private beginNamespace(type: genspec.CodeName) {
if (type.namespace) {
const parts = type.namespace.split('.');
Expand Down Expand Up @@ -555,7 +572,13 @@ export default class CodeGenerator {
Object.keys(propTypeSpec.Properties).forEach(propName => {
const propSpec = propTypeSpec.Properties[propName];
const additionalDocs = quoteCode(`${typeName.fqn}.${propName}`);
const newName = this.emitProperty(resourceContext, propName, propSpec, additionalDocs);
const newName = this.emitProperty({
context: resourceContext,
propName,
spec: propSpec,
additionalDocs,
container: Container.Interface,
});
conversionTable[propName] = newName;
});
}
Expand Down Expand Up @@ -702,3 +725,33 @@ function tagType(resource: schema.ResourceType): string {
}
return `${TAG_TYPE}.NotTaggable`;
}

enum Container {
Interface = 'INTERFACE',
Class = 'CLASS',
}

interface EmitPropertyProps {
context: genspec.CodeName;
propName: string;
spec: schema.Property;
additionalDocs: string;
container: Container;
}

// remove export
// export class PropertyGenerator {
//
// private readonly resource: genspec.CodeName;
// private readonly spec: schema.ResourceType;
//
// constructor(resourceContext: genspec.CodeName, spec: schema.ResourceType) {
// this.resource = resourceContext;
// this.spec = spec;
// }
//
// // const conversionTable = this.emitPropsTypeProperties(resourceContext, spec.Properties);
// public hasProperties(): boolean {
// return this.spec.Properties ? Object.keys(this.spec.Properties).length > 0 : false;
// }
// }

0 comments on commit af39691

Please sign in to comment.