docs: function processModels(swagger, options) {
    var name, model, i, property;
    var models = {};
    for (name in swagger.definitions) {
      model = swagger.definitions[name];
      var parent = null;
      var properties = null;
      var requiredProperties = null;
      var additionalPropertiesType = false;
      var example = model.example || null;
      var enumValues = null;
      var elementType = null;
      var simpleType = null;
      if (model.allOf != null && model.allOf.length > 0) {
        parent = simpleRef((model.allOf[0] || {}).$ref);
        properties = (model.allOf[1] || {}).properties || {};
        requiredProperties = (model.allOf[1] || {}).required || [];
      } else if (model.type === 'string') {
        enumValues = model.enum || [];
        if (enumValues.length == 0) {
          simpleType = 'string';
          enumValues = null;
        } else {
          for (i = 0; i < enumValues.length; i++) {
            var enumValue = enumValues[i];
            var enumDescriptor = {
              enumName: toEnumName(enumValue),
              enumValue: enumValue,
              enumIsLast: i === enumValues.length - 1,
            };
            enumValues[i] = enumDescriptor;
          }
        }
      } else if (model.type === 'array') {
        elementType = propertyType(model);
      } else if (!model.type && (model.anyOf || model.oneOf)) {
        let of = model.anyOf || model.oneOf;
        let variants = of.map(propertyType);
        simpleType = {
          allTypes: mergeTypes(...variants),
          toString: () => variants.join(' |\n  ')
        };
      } else if (model.type === 'object' || model.type === undefined) {
        properties = model.properties || {};
        requiredProperties = model.required || [];
        additionalPropertiesType = model.additionalProperties &&
            (typeof model.additionalProperties === 'object' ? propertyType(model.additionalProperties) : 'any');
      } else {
        simpleType = propertyType(model);
      }
      var modelClass = toClassName(name);
      var descriptor = {
        modelName: name,
        modelClass: modelClass,
        modelFile: toFileName(modelClass),
        modelComments: toComments(model.description),
        modelParent: parent,
        modelIsObject: properties != null,
        modelIsEnum: enumValues != null,
        modelIsArray: elementType != null,
        modelIsSimple: simpleType != null,
        modelSimpleType: simpleType,
        properties: properties == null ? null :
          processProperties(swagger, properties, requiredProperties),
        modelExample: example,
        modelAdditionalPropertiesType: additionalPropertiesType,
        modelExampleFile: toExampleFileName(name),
        modelEnumValues: enumValues,
        modelElementType: elementType,
        modelSubclasses: [],
      };
  
      if (descriptor.properties != null) {
        descriptor.modelProperties = [];
        for (var propertyName in descriptor.properties) {
          property = descriptor.properties[propertyName];
          descriptor.modelProperties.push(property);
        }
        descriptor.modelProperties.sort((a, b) => {
          return a.modelName < b.modelName ? -1 :
            a.modelName > b.modelName ? 1 : 0;
        });
        if (descriptor.modelProperties.length > 0) {
          descriptor.modelProperties[
            descriptor.modelProperties.length - 1
          ].propertyIsLast = true;
        }
      }
  
      models[name] = descriptor;
      models[descriptor.modelClass] = descriptor;
    }
  
    // Now that we know all models, process the hierarchies
    for (name in models) {
      model = models[name];
      if (!model.modelIsObject) {
        // Only objects can have hierarchies
        continue;
      }
  
      // Process the hierarchy
      var parentName = model.modelParent;
      if (parentName) {
        // Make the parent be the actual model, not the name
        model.modelParent = models[parentName];
  
        // Append this model on the parent's subclasses
        model.modelParent.modelSubclasses.push(model);
      }
    }
  
    // Now that the model hierarchy is ok, resolve the dependencies
    var addToDependencies = t => {
      if (Array.isArray(t.allTypes)) {
        t.allTypes.forEach(it => dependencies.add(it));
      }
      else dependencies.add(t);
    };
    for (name in models) {
      model = models[name];
      if (model.modelIsEnum || model.modelIsSimple && !model.modelSimpleType.allTypes) {
        // Enums or simple types have no dependencies
        continue;
      }
      var dependencies = new DependenciesResolver(models, model.modelName);
  
      // The parent is a dependency
      if (model.modelParent) {
        dependencies.add(model.modelParent.modelName);
      }
  
      // Each property may add a dependency
      if (model.modelProperties) {
        for (i = 0; i < model.modelProperties.length; i++) {
          property = model.modelProperties[i];
          addToDependencies(property.propertyType);
        }
      }
  
      // If an array, the element type is a dependency
      if (model.modelElementType) addToDependencies(model.modelElementType);
  
      if (model.modelSimpleType) addToDependencies(model.modelSimpleType);
  
      if (model.modelAdditionalPropertiesType) addToDependencies(model.modelAdditionalPropertiesType);
  
      model.modelDependencies = dependencies.get();
    }
  
    return models;
  }