code: def all_slots(self, cls: CLASS_OR_CLASSNAME, *, cls_slots_first: bool = False) \
              -> List[SlotDefinition]:
          
          def merge_definitions(cls_name: Optional[ClassDefinitionName]) -> None:
              if cls_name:
                  for slot in self.all_slots(cls_name):
                      aliased_name = self.aliased_slot_name(slot)
                      if aliased_name not in known_slots:
                          known_slots.add(aliased_name)
                          rval.append(slot)
  
          if not isinstance(cls, ClassDefinition):
              cls = self.schema.classes[cls]
          known_slots: Set[str] = self.aliased_slot_names(cls.slots)
          rval: List[SlotDefinition] = []
  
          if cls_slots_first:
              rval += self.cls_slots(cls)
              for mixin in cls.mixins:
                  merge_definitions(mixin)
              merge_definitions(cls.is_a)
          else:
              merge_definitions(cls.is_a)
              for mixin in cls.mixins:
                  merge_definitions(mixin)
              rval += self.cls_slots(cls)
  
          return rval
docs: Return all slots that are part of the class definition.  This includes all is_a, mixin and apply_to slots
          but does NOT include slot_usage targets.  If class B has a slot_usage entry for slot "s", only the slot
          definition for the redefined slot will be included, not its base.  Slots are added in the order they appear
          in classes, with recursive is_a's being added first followed by mixins and finally apply_tos
  
          @param cls: class definition or class definition name
          @param cls_slots_first: True means return class slots at the top of the list
          @return: ordered list of slots in the class with slot usages removed