docs: def resolve(self) -> SchemaDefinition:
          """ Return a fully resolved schema
          """
  
          if not isinstance(self.schema.slots, dict):
              raise ValueError(f"File: {self.schema.source_file} Slots are not a dictionary")
  
          if not isinstance(self.schema.classes, dict):
              raise ValueError(f"File: {self.schema.source_file} Classes are not a dictionary")
  
          # Process imports
          for sname in self.schema.imports:
              if sname not in self.loaded:
                  self.loaded.add(sname)
                  merge_schemas(self.schema, load_raw_schema(sname + '.yaml', base_dir=self.base_dir))
  
          # slot.domain --> class.slots
          for slot in self.schema.slots.values():
              if slot.domain in self.schema.classes and slot.name not in self.schema.classes[slot.domain].slots:
                  self.schema.classes[slot.domain].slots.append(slot.name)
  
          # class.slots --> slot.domain
          for cls in self.schema.classes.values():
              if not isinstance(cls, ClassDefinition):
                  raise ValueError(
                      f'File: {self.schema.source_file} Class "{cls} (type: {type(cls)})" definition is peculiar')
              if isinstance(cls.slots, str):
                  print(f"File: {self.schema.source_file} Class: {cls.name} Slots are not an array", file=sys.stderr)
                  cls.slots = [cls.slots]
              for slotname in cls.slots:
                  if slotname in self.schema.slots:
                      if self.schema.slots[slotname].domain is None:
                          self.schema.slots[slotname].domain = cls.name
  
          # apply to --> mixins
          for cls in self.schema.classes.values():
              if cls.apply_to in self.schema.classes:
                  self.schema.classes[cls.apply_to].mixins.append(cls.name)
  
          # Override class slots with slot usage definitions
          for cls in self.schema.classes.values():
              for slot_name, slot_usage in cls.slot_usage.items():
                  # Construct a new slot
                  # Follow the ancestry of the class to get the most proximal parent
                  parent_slot = self.slot_definition_for(slot_name, cls)
                  if not parent_slot and slot_name in self.schema.slots:
                      parent_slot = self.schema.slots[slot_name]
                  # If parent slot is still not defined, it means that we introduced a NEW slot in the slot usages
                  child_name = SlotDefinitionName(cls.name + ' ' + slot_name) if parent_slot else slot_name
                  new_slot = SlotDefinition(name=child_name, alias=slot_name, domain=cls.name)
                  merge_slots(new_slot, slot_usage)
  
                  # Copy the parent definition.  If there is no parent definition, the slot is being defined
                  # locally as a slot_usage
                  if parent_slot is not None:
                      new_slot.is_a = parent_slot.name
                      merge_slots(new_slot, parent_slot)
  
                  # Add the slot usage overrides
                  merge_slots(new_slot, slot_usage)
                  self.schema.slots[child_name] = new_slot
  
                  # Add or replace the slot in the class definition
                  append = True
                  for i, s in enumerate(cls.slots):
                      if s == slot_name:
                          cls.slots[i] = SlotDefinitionName(child_name)
                          append = False
                          break
                  if append:
                      cls.slots.append(SlotDefinitionName(child_name))
  
          # Update slots with parental information
          merged_slots: List[SlotDefinition] = []
          for slot in self.schema.slots.values():
              self.merge_slot(slot, merged_slots)
  
          # Clean up the slot range defaults
          for slot in self.schema.slots.values():
              if not slot.range:
                  slot.range = 'string'
  
          return self.schema