function runNextPlugin () {
    plugin = plugins[index++];
    if (!plugin) {
      // There are no more functions, so re-throw the last error
      return reject(lastError);
    }

    try {
      debug('  %s', plugin.name);
      var result = getResult(plugin, method, file, callback);
      if (result && typeof result.then === 'function') {
        // A promise was returned
        result.then(onSuccess, onError);
      }
      else if (result !== undefined) {
        // A synchronous result was returned
        onSuccess(result);
      }
      // else { the callback will be called }
    }
    catch (e) {
      onError(e);
    }
  }
Runs the specified method of the given plugins, in order, until one of them returns a successful result.
Each method can return a synchronous value, a Promise, or call an error-first callback.
If the promise resolves successfully, or the callback is called without an error, then the result
is immediately returned and no further plugins are called.
If the promise rejects, or the callback is called with an error, then the next plugin is called.
If ALL plugins fail, then the last error is thrown.

@param {object[]}  plugins - An array of plugin objects
@param {string}    method  - The name of the method to invoke for each plugin
@param {object}    file    - A file info object, which will be passed to each method
@returns {Promise}