/**
 * @class Cmd.auto.Dependency
 * 
 * The Cmd Auto Dependency system is an api that allows Cmd to automatically detect class
 * dependencies based purely on usages in code without needing to reference a needed class
 * in either the requires or uses arrays.
 * 
 * It works by combining the values of class configs with metadata from associated auto
 * dependency directives to allow Cmd to interpret the value of a config as a constructor
 * parameter to another class.
 * 
 * As an example, consider the following auto dependency directive for the `items` config
 * of the Container class from the classic toolkit:
 *
 *      Ext.define('Ext.container.Container', {
 *          ...
 *          // @cmd-auto-dependency {aliasPrefix: "widget.", typeProperty: "xtype", defaultTypeProperty: "defaultType", defaultsProperty: "defaults"}
 *          items: undefined,
 *          ...
 *      });
 * 
 * Cmd requires the directive to be contained in a single line, but for the purposes of 
 * discussing the structure of the directive, here is the same directive formatted for 
 * readability:
 * 
 *      Ext.define('Ext.container.Container', {
 *          ...
 *          // @cmd-auto-dependency {
 *          //     aliasPrefix: "widget.", 
 *          //     typeProperty: "xtype", 
 *          //     defaultTypeProperty: "defaultType", 
 *          //     defaultsProperty: "defaults"
 *          // }
 *          items: undefined,
 *          ...
 *      });
 * 
 * In this example, the presence of the cmd-auto-dependency directive above the items
 * config is enough to indicate to Cmd that the value of an items config, when supplied,
 * should be processed as a constructor parameter to one or more class instances.
 * 
 * To do this, Cmd must first determine the class being constructed.  It does this by first
 * looking at the value of the config.  If the value of the config is a string, like:
 * 
 *      new Ext.container.Container({
 *          items: "button"
 *      });
 * 
 * the value of the string is first checked to see if it is already a resolvable reference
 * to a class definition.  If not, the data from the directive is used to produce other 
 * match candidates.  In this case, the directive indicates that the `aliasPrefix` to use
 * when resolving class names here is "widget.", so the name, "button", is combined with 
 * the `aliasPrefix` to produce the candidate name "widget.button", which will resolve to 
 * Ext.button.Button.
 * 
 * If, however, the value of the config is an object literal, the the object literal will 
 * need to be inspected to determine the string literal to use.
 *
 *      new Ext.container.Container({
 *          items: {
 *              xtype: "button"
 *          }
 *      });
 * 
 * To determine the class name for configs of this type, Cmd must inspect the object
 * literal to detect a specified class name. In this case, the directive specifies a 
 * `typeProperty` of "xtype".  This tells Cmd that if the object literal contains a property
 * by that name, then the value of that property should be used as the input string to 
 * perform the above lookup.
 * 
 * For container items, an array may also be supplied as the value of the config.  In this
 * case, Cmd will iterate all of the items of the array, applying the same class name
 * lookup process:
 *
 *      new Ext.container.Container({
 *          items: [{
 *              xtype: "button"
 *          },{
 *              xtype: "panel"
 *          }]
 *      });
 * 
 * In some cases, the data needed to create the target class name may be provided via 
 * another property on the class definition, and `defaultTypeProperty` allows this property
 * name to be specified.  For the items config, the `defaultTypeProperty` value of 
 * "defaultType" indicates that the "defaultType" property should be used if supplied:
 *
 *      new Ext.container.Container({
 *          defaultType: "button",
 *          items: [{
 *              text: "abc"
 *          },{
 *              xtype: "panel"
 *          }]
 *      });
 * 
 * The auto dependency system can also handle the case where a class definition supplies
 * an entire default config to use when creating certain class instances.  For container
 * items, this is configured with the `defaultsProperty` of "defaults":
 *
 *      new Ext.container.Container({
 *          defaults: {
 *              xtype: "button",
 *              text: "abc"
 *          },
 *          items: [{
 *              label: "xyz"
 *          },{
 *              xtype: "panel"
 *          }]
 *      });
 * 
 * For other configs less dynamic than container items, or for cases where the default type
 * to looks up does not need to be dynamically modified, the `defaultType` dependency 
 * property may be used to set the default type to use when no other type info is found
 * on the config value.
 * 
 * In other cases, while the config value itself may need to be processed to determine 
 * further dependencies, there may be other helper classes required by the config that 
 * can not be found by inspecting the config value itself.  In these cases, the `requires`
 * dependency config may be used to list other classes that should be required when a 
 * config value is supplied
 * 
 * 
 * One subtlety of the auto dependency system is that the detection of requirements is 
 * driven by the instantiation points, not the class definitions.  Consider the following 
 * example:
 *
 *      Ext.define("A.container.Class", {
 *          // @cmd-auto-dependency { aliasPrefix: "layout." }
 *          // an optional layout config, "layout.hbox" will be the default
 *          layout: "hbox"
 *      });
 *
 *      Ext.create("A.container.Class", {
 *          layout: "vbox"
 *      });
 *
 * In this example, the 'layout.hbox' class will never be required, even though it is 
 * the default layout for the class, since there are no instances of the container class 
 * that use the hbox layout, only vbox.
 * 
 * @private
 */
 
/**
 * @cfg {String} defaultType
 * This config specifies the default type name to use when resolving a config value.  
 * 
 *      Ext.define("A.button.Class", {
 *          // @cmd-auto-dependency { defaultType: "Ext.menu.Menu" }
 *          // an optional popup menu
 *          menu: undefined
 *      });
 * 
 *      Ext.create("A.button.Class", {
 *          // no xtype needed, as the defaultType will be applied
 *          menu: {
 *              items: [...]
 *          }
 *      });
 * 
 */
 
/**
 * @cfg {String} typeProperty
 * Specifies the property to inspect when looking for a type specifier.  The default 
 * value for this is 'type'.
 *
 *      Ext.define("A.button.Class", {
 *          // @cmd-auto-dependency { defaultType: "Ext.menu.Menu", typeProperty: 'mtype' }
 *          // an optional popup menu
 *          menu: undefined
 *      });
 *
 *      Ext.create("A.button.Class", {
 *          menu: {
 *              // this overrides the default type with a custom value
 *              mtype: 'custom-menu'
 *              items: [...]
 *          }
 *      });
 * 
 */
 
/**
 * @cfg {String} defaultTypeProperty
 * Specifies a property / config on the class definition that will contain the default
 * value to use when resolving the class name.
 *
 *      Ext.define("A.container.Class", {
 *          // @cmd-auto-dependency { defaultTypeProperty: "defaultType" }
 *          items: undefined
 *      });
 *      
 *      new A.container.Class({
 *          defaultType: "button",
 *          items: [{
 *              // xtype not needed for this item, as "button" will be used
 *              // as the default type
 *              text: "abc"
 *          },{
 *              xtype: "panel"
 *          }]
 *      });
 */
 
/**
 * @cfg {String} aliasPrefix
 * This property specifies an alias prefix to prepend to the detected name value when 
 * generating name matching candidates for the  type lookup.
 * 
 *      Ext.define("A.container.Class", {
 *          // @cmd-auto-dependency { aliasPrefix: "layout." }
 *          // an optional layout config, "layout.hbox" will be the default
 *          layout: "hbox"
 *      });
 *      
 *      Ext.create("A.container.Class", {
 *          layout: "vbox"
 *      });
 */
 
/**
 * @cfg {String[]} requires
 * Specifies a list of other classes that need to be requires when a config is supplied, 
 * but that are not detectable via the value of the config.
 *
 *      Ext.define("An.application.Class", {
 *          // @cmd-auto-dependency { aliasPrefix: "view.", requires: ["Ext.plugin.Viewport"]}
 *          mainView: null
 *      });
 *
 *      Ext.define("A.view.Class", {
 *          alias: "view.main"
 *      });
 * 
 *      Ext.create("A.application.Class", {
 *          mainView: "main"
 *      });
 */
 
/**
 * @cfg {String} directRef
 * Similar to requires, but specifies a single class to automatically be required
 * if a truthy value for this config is specified.
 * @private
 */
 
/**
 * @cfg {boolean} isKeyedObject
 * Indicates that when an object literal value is supplied, this value should be processed
 * as a key/value container where the values are the configs to inspect, similar to the 
 * array form of config value.
 * 
 *      Ext.define('A.field.Class', {
 *          // @cmd-auto-dependency { aliasPrefix: "trigger.", isKeyedObject: true}
 *          triggers: null
 *      });
 *      
 *      Ext.create('A.field.Class', {
 *          triggers: {
 *              clear: 'clear',
 *              search: {
 *                  type: 'search'
 *              }
 *          }
 *      });
 */
 
/**
 * @cfg {String} blame
 * Controls whether the instantiation point, the class definition, or both gain the 
 * dependency when a value is supplied for this class config.  Useful for controlling 
 * file sort ordering.
 * 
 * Supported values are `class`, `instance`, or `all`. The default value is `instance` 
 * 
 * Considering the following example:
 * 
 *      // A.js content
 *      Ext.define('A.button.Class', {
 *          // @cmd-auto-dependency { defaultType: "Ext.menu.Menu", blame: "instance" }
 *          menu: undefined
 *      });
 *      
 *      // B.js content
 *      Ext.create('A.button.Class', {
 *          menu: {...} 
 *      });
 *      
 * A the default blame value of 'instance' indicates that B.js should gain the requirement
 * for Ext.menu.Menu.  A blame value of 'class' would cause A.js to gain the requirement.
 * A blame value of 'all' would cause both A.js and B.js to gain the requirement.
 */