text: // sourcery:file: skipEquality
  import Foundation
  
  /// Class that represents a project element.
  public class PBXObject: Hashable, Decodable, Equatable, AutoEquatable {
      /// Returns the unique identifier.
      /// Note: The unique identifier of an object might change when the project gets written.
      /// If you use this identifier from a scheme, make sure the project is written before the project is.
      public var uuid: String {
          reference.value
      }
  
      /// The object reference in the project that contains it.
      let reference: PBXObjectReference
  
      /**
       Used to differentiate this object from other equatable ones for the purposes of uuid generation.
  
       This shouldn't be required to be set in normal circumstances.
       In some rare cases xcodeproj doesn't have enough context about otherwise equatable objects,
       so it has to resolve automatic uuid conflicts by appending numbers.
       This property can be used to provide more context to disambiguate these objects,
       which will result in more deterministic uuids.
       */
      public var context: String?
  
      // MARK: - Init
  
      init() {
          reference = PBXObjectReference()
          reference.setObject(self)
      }
  
      // MARK: - Decodable
  
      fileprivate enum CodingKeys: String, CodingKey {
          case reference
      }
  
      /// Initializes the object from its project representation.
      ///
      /// - Parameter decoder: XcodeprojPropertyListDecoder decoder.
      /// - Throws: an error if the object cannot be parsed.
      public required init(from decoder: Decoder) throws {
          let referenceRepository = decoder.context.objectReferenceRepository
          let objects = decoder.context.objects
          let container = try decoder.container(keyedBy: CodingKeys.self)
          let reference: String = try container.decode(.reference)
          self.reference = referenceRepository.getOrCreate(reference: reference, objects: objects)
          self.reference.setObject(self)
      }
  
      /// Object isa (type id)
      public static var isa: String {
          String(describing: self)
      }
  
      public static func == (lhs: PBXObject,
                             rhs: PBXObject) -> Bool {
          lhs.isEqual(to: rhs)
      }
  
      @objc dynamic func isEqual(to _: Any?) -> Bool {
          true
      }
  
      public func hash(into hasher: inout Hasher) {
          hasher.combine(reference)
      }
  
      /// Returns the objects the object belong to.
      ///
      /// - Returns: objects the object belongs to.
      /// - Throws: an error if this method is accessed before the object has been added to a project.
      func objects() throws -> PBXObjects {
          guard let objects = reference.objects else {
              let objectType = String(describing: type(of: self))
              throw PBXObjectError.orphaned(type: objectType, reference: reference.value)
          }
          return objects
      }
  }
  