def _generate_union_type(self, union_type, indent_spaces): """ Generates a TypeScript interface for a stone union. """ # Emit an interface for each variant. TypeScript 2.0 supports these tagged unions. # https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#tagged-union-types parent_type = union_type.parent_type namespace = union_type.namespace union_type_name = fmt_type_name(union_type, namespace) variant_type_names = [] if parent_type: variant_type_names.append(fmt_type_name(parent_type, namespace)) for variant in union_type.fields: if variant.doc: self._emit_tsdoc_header(variant.doc) variant_name = '%s%s' % (union_type_name, fmt_pascal(variant.name)) variant_type_names.append(variant_name) self.emit('interface %s {' % variant_name) with self.indent(dent=indent_spaces): # Since field contains non-alphanumeric character, we need to enclose # it in quotation marks. self.emit("'.tag': '%s';" % variant.name) if is_void_type(variant.data_type) is False: self.emit("%s: %s;" % (variant.name, fmt_type(variant.data_type, namespace))) self.emit('}') self.emit() if union_type.doc: self._emit_tsdoc_header(union_type.doc) self.emit('type %s = %s;' % (union_type_name, ' | '.join(variant_type_names))) self.emit()
def _generate_alias_type(self, alias_type): """ Generates a TypeScript type for a stone alias. """ namespace = alias_type.namespace self.emit('type %s = %s;' % (fmt_type_name(alias_type, namespace), fmt_type_name(alias_type.data_type, namespace))) self.emit()
def _generate_union_type(self, union_type, indent_spaces): """ Generates a TypeScript interface for a stone union. """ # Emit an interface for each variant. TypeScript 2.0 supports these tagged unions. # https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#tagged-union-types parent_type = union_type.parent_type namespace = union_type.namespace union_type_name = fmt_type_name(union_type, namespace) variant_type_names = [] if parent_type: variant_type_names.append(fmt_type_name(parent_type, namespace)) def _is_struct_without_enumerated_subtypes(data_type): """ :param data_type: any data type. :return: True if the given data type is a struct which has no enumerated subtypes. """ return is_struct_type(data_type) and ( not data_type.has_enumerated_subtypes()) for variant in union_type.fields: if variant.doc: self._emit_tsdoc_header(variant.doc) variant_name = '%s%s' % (union_type_name, fmt_pascal(variant.name)) variant_type_names.append(variant_name) is_struct_without_enumerated_subtypes = _is_struct_without_enumerated_subtypes( variant.data_type) if is_struct_without_enumerated_subtypes: self.emit( 'export interface %s extends %s {' % (variant_name, fmt_type(variant.data_type, namespace))) else: self.emit('export interface %s {' % variant_name) with self.indent(dent=indent_spaces): # Since field contains non-alphanumeric character, we need to enclose # it in quotation marks. self.emit("'.tag': '%s';" % variant.name) if is_void_type(variant.data_type) is False and ( not is_struct_without_enumerated_subtypes): self.emit( "%s: %s;" % (variant.name, fmt_type(variant.data_type, namespace))) self.emit('}') self.emit() if union_type.doc: self._emit_tsdoc_header(union_type.doc) self.emit('export type %s = %s;' % (union_type_name, ' | '.join(variant_type_names))) self.emit()
def _generate_union_type(self, union_type, indent_spaces): """ Generates a TypeScript interface for a stone union. """ # Emit an interface for each variant. TypeScript 2.0 supports these tagged unions. # https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#tagged-union-types parent_type = union_type.parent_type namespace = union_type.namespace union_type_name = fmt_type_name(union_type, namespace) variant_type_names = [] if parent_type: variant_type_names.append(fmt_type_name(parent_type, namespace)) def _is_struct_without_enumerated_subtypes(data_type): """ :param data_type: any data type. :return: True if the given data type is a struct which has no enumerated subtypes. """ return is_struct_type(data_type) and ( not data_type.has_enumerated_subtypes()) for variant in union_type.fields: if variant.doc: self._emit_tsdoc_header(variant.doc) variant_name = '%s%s' % (union_type_name, fmt_pascal(variant.name)) variant_type_names.append(variant_name) is_struct_without_enumerated_subtypes = _is_struct_without_enumerated_subtypes( variant.data_type) if is_struct_without_enumerated_subtypes: self.emit('export interface %s extends %s {' % ( variant_name, fmt_type(variant.data_type, namespace))) else: self.emit('export interface %s {' % variant_name) with self.indent(dent=indent_spaces): # Since field contains non-alphanumeric character, we need to enclose # it in quotation marks. self.emit("'.tag': '%s';" % variant.name) if is_void_type(variant.data_type) is False and ( not is_struct_without_enumerated_subtypes ): self.emit("%s: %s;" % (variant.name, fmt_type(variant.data_type, namespace))) self.emit('}') self.emit() if union_type.doc: self._emit_tsdoc_header(union_type.doc) self.emit('export type %s = %s;' % (union_type_name, ' | '.join(variant_type_names))) self.emit()
def _generate_struct_type(self, struct_type, indent_spaces, extra_parameters): """ Generates a TypeScript interface for a stone struct. """ namespace = struct_type.namespace if struct_type.doc: self._emit_tsdoc_header(struct_type.doc) parent_type = struct_type.parent_type extends_line = ' extends %s' % fmt_type_name(parent_type, namespace) if parent_type else '' self.emit('interface %s%s {' % (fmt_type_name(struct_type, namespace), extends_line)) with self.indent(dent=indent_spaces): for param_name, param_type, param_docstring in extra_parameters: if param_docstring: self._emit_tsdoc_header(param_docstring) self.emit('%s: %s;' % (param_name, param_type)) for field in struct_type.fields: doc = field.doc field_type, nullable = unwrap_nullable(field.data_type) field_ts_type = fmt_type(field_type, namespace) optional = nullable or field.has_default if field.has_default: # doc may be None. If it is not empty, add newlines # before appending to it. doc = doc + '\n\n' if doc else '' doc = "Defaults to %s." % field.default if doc: self._emit_tsdoc_header(doc) # Translate nullable types into optional properties. field_name = '%s?' % field.name if optional else field.name self.emit('%s: %s;' % (field_name, field_ts_type)) self.emit('}') self.emit() # Some structs can explicitly list their subtypes. These structs have a .tag field that # indicate which subtype they are, which is only present when a type reference is # ambiguous. # Emit a special interface that contains this extra field, and refer to it whenever we # encounter a reference to a type with enumerated subtypes. if struct_type.is_member_of_enumerated_subtypes_tree(): if struct_type.has_enumerated_subtypes(): # This struct is the parent to multiple subtypes. Determine all of the possible # values of the .tag property. tag_values = [] for tags, _ in struct_type.get_all_subtypes_with_tags(): for tag in tags: tag_values.append('"%s"' % tag) tag_union = fmt_union(tag_values) self._emit_tsdoc_header('Reference to the %s polymorphic type. Contains a .tag ' 'property to let you discriminate between possible ' 'subtypes.' % fmt_type_name(struct_type, namespace)) self.emit('interface %s extends %s {' % (fmt_polymorphic_type_reference(struct_type, namespace), fmt_type_name(struct_type, namespace))) with self.indent(dent=indent_spaces): self._emit_tsdoc_header('Tag identifying the subtype variant.') self.emit('\'.tag\': %s;' % tag_union) self.emit('}') self.emit() else: # This struct is a particular subtype. Find the applicable .tag value from the # parent type, which may be an arbitrary number of steps up the inheritance # hierarchy. parent = struct_type.parent_type while not parent.has_enumerated_subtypes(): parent = parent.parent_type # parent now contains the closest parent type in the inheritance hierarchy that has # enumerated subtypes. Determine which subtype this is. for subtype in parent.get_enumerated_subtypes(): if subtype.data_type == struct_type: self._emit_tsdoc_header('Reference to the %s type, identified by the ' 'value of the .tag property.' % fmt_type_name(struct_type, namespace)) self.emit('interface %s extends %s {' % (fmt_polymorphic_type_reference(struct_type, namespace), fmt_type_name(struct_type, namespace))) with self.indent(dent=indent_spaces): self._emit_tsdoc_header('Tag identifying this subtype variant. This ' 'field is only present when needed to ' 'discriminate between multiple possible ' 'subtypes.') self.emit_wrapped_text('\'.tag\': \'%s\';' % subtype.name) self.emit('}') self.emit() break