Adds a required class

@param name {String} the name of the class
@param opts {Map?} which is:

@param where {"ignore"|"require"|"use"|null} where it's mentioned
@param load {Boolean?} whether it is a load-time dependency or not
@param defer {Boolean?} whether the dependency is in defer or not
@return {Map?} info about the symbol type of the named class, @see {Analyser.getSymbolType}
function(name, opts) {
      if (qx.lang.Type.isArray(name)) {
        name.forEach(name => this._requireClass(name));
        return null;
      }
      let t = this;
      if (name == this.__className) {
        return null; 
      }
      if (!name) {
        throw new Error("No classname");
      }
      if (this.isIgnored(name)) {
        return null;
      }
      
      let requireOpts = {
        load: t.isLoadScope(),
        defer: t.__inDefer,
        construct: t.__classMeta && t.__classMeta.functionName == "$$constructor"
      };
      if (opts) {
        for (let key in opts) {
          requireOpts[key] = opts[key];
        } 
      }

      let info = t.__analyser.getSymbolType(name);
      let symbolType = info ? info.symbolType : null;
      let className = info ? info.className : null;
      if (symbolType != "package" && className && className != t.__className) {
        // Re-check the class name as ignored if this is a member
        if (symbolType == "member" && t.isIgnored(className)) {
          return null; 
        }
        let data = t.__requiredClasses[className];
        if (!data) {
          data = t.__requiredClasses[className] = {};
        }

        if (requireOpts.where !== undefined) {
          if (requireOpts.where == "ignore") {
            data.ignore = true;
          } else if (requireOpts.where == "require") {
            data.require = true;
          }
        }
        if (requireOpts.load) {
          data.load = true;
          if (requireOpts.usage === "dynamic") {
            if (data.usage !== "static") {
              data.usage = "dynamic";
            }
            data.load = true;
          } else if (!data.load) {
            data.load = true;
            data.usage = "static";
          }
        }
        if (requireOpts.defer) {
          if (requireOpts.load) {
            data.defer = "load";
          } else if (data.defer !== "load") {
            data.defer = "runtime";
          }
          
          if (!name.startsWith(t.__className)) {
            if (!qx.tool.compiler.ClassFile.DEFER_SAFE_SYMBOLS.some(function(symbol) {
              return name.startsWith(symbol);
            })) {
              // Temporarily disabled until Qooxdoo framework catches up
              // t.addMarker("defer.unsafe", (opts && opts.location)||null, name);
            }
          }
        }
        if (requireOpts.construct) {
          data.construct = true;
        }
        t.deleteReference(className);
      }
      return info;
    }