code: def linearize_data_types(self):
          # type: () -> typing.List[UserDefined]
          
          linearized_data_types = []
          seen_data_types = set()  # type: typing.Set[UserDefined]
  
          def add_data_type(data_type):
              # type: (UserDefined) -> None
              if data_type in seen_data_types:
                  return
              elif data_type.namespace != self:
                  # We're only concerned with types defined in this namespace.
                  return
              if is_composite_type(data_type) and data_type.parent_type:
                  add_data_type(data_type.parent_type)
              linearized_data_types.append(data_type)
              seen_data_types.add(data_type)
  
          for data_type in self.data_types:
              add_data_type(data_type)
  
          return linearized_data_types
docs: Returns a list of all data types used in the namespace. Because the
          inheritance of data types can be modeled as a DAG, the list will be a
          linearization of the DAG. It's ideal to generate data types in this
          order so that composite types that reference other composite types are
          defined in the correct order.