code: private function getFieldDef(Schema $schema, ObjectType $parentType, $fieldName)
      {
          static $schemaMetaFieldDef, $typeMetaFieldDef, $typeNameMetaFieldDef;
          $schemaMetaFieldDef   = $schemaMetaFieldDef ?: Introspection::schemaMetaFieldDef();
          $typeMetaFieldDef     = $typeMetaFieldDef ?: Introspection::typeMetaFieldDef();
          $typeNameMetaFieldDef = $typeNameMetaFieldDef ?: Introspection::typeNameMetaFieldDef();
          if ($fieldName === $schemaMetaFieldDef->name && $schema->getQueryType() === $parentType) {
              return $schemaMetaFieldDef;
          }
  
          if ($fieldName === $typeMetaFieldDef->name && $schema->getQueryType() === $parentType) {
              return $typeMetaFieldDef;
          }
  
          if ($fieldName === $typeNameMetaFieldDef->name) {
              return $typeNameMetaFieldDef;
          }
          $tmp = $parentType->getFields();
  
          return $tmp[$fieldName] ?? null;
      }
docs: This method looks up the field on the given type definition.
  It has special casing for the two introspection fields, __schema
  and __typename. __typename is special because it can always be
  queried as a field, even in situations where no other fields
  are allowed, like on a Union. __schema could get automatically
  added to the query type, but that would require mutating type
  definitions, which would cause issues.
  
  @param string $fieldName
  
  @return FieldDefinition