whole_func_string: async function() {
        var t = this;
        var compileAst = null;
        var compileJson = {};
        var configJson;
  
        var lets = {};
        function getMacro(name) {
          var value = lets[name];
          value = replaceMacros(value);
          return value;
        }
  
        function replaceMacros(value) {
          if (!value) {
            return "";
          }
          // eslint-disable-next-line no-constant-condition
          while (true) {
            var pos = value.indexOf("${");
            var endPos = value.indexOf("}", pos);
            if (pos < 0 || endPos < 0) {
              return value;
            }
            var name = value.substring(pos + 2, endPos);
            var left = value.substring(0, pos);
            var right = value.substring(endPos + 1);
            value = left + lets[name] + right;
          }
        }
  
        function parseJson(str) {
          var ast = JsonToAst.parseToAst(str);
          var json = JsonToAst.astToObject(ast);
          return json;
        }
  
        t.debug(">>> Loading config.json");
        var data;
        try {
          data = await readFile("config.json", {encoding: "utf8"});
        } catch (ex) {
          if (ex.code == "ENOENT") {
            return;
          }
          throw new qx.tool.cli.Utils.UserError("Cannot read config.json: " + (ex.message||ex.stack));
        }
        try {
          configJson = parseJson(data);
        } catch (ex) {
          throw new qx.tool.cli.Utils.UserError("Cannot parse config.json: " + (ex.message||ex.stack));
        }
  
        t.debug(">>> Loading compile.json (if there is one)");
        try {
          data = await readFile("compile.json", {encoding: "utf8"});
          try {
            compileAst = JsonToAst.parseToAst(data, {verbose: true});
            compileJson = JsonToAst.astToObject(compileAst);
          } catch (ex) {
            throw new qx.tool.cli.Utils.UserError("Cannot parse compile.json: " + (ex.message||ex.stack));
          }
        } catch (err) {
          if (err.code !== "ENOENT") {
            throw err;
          }
        }
  
        t.debug(">>> Loading Manifest.json");
        try {
          var str = await readFile("Manifest.json", {encoding: "utf8"});
          data = parseJson(str);
        } catch (ex) {
          data = null;
        }
  
        lets = (configJson && configJson["let"])||{};
        compileJson = Object.assign({
          applications: [],
          libraries: [],
          targets: [
            {
              "type": "source",
              "outputPath": "compiled/source"
            },
            {
              "type": "build",
              "outputPath": "compiled/build"
            }
          ],
          defaultTarget: "source",
          locales: getMacro("LOCALES")|| ["en"]
        }, compileJson);
  
        if (compileJson.libraries) {
          compileJson.libraries = compileJson.libraries.map(function(path) {
            if (typeof path === "object" && typeof path.path === "string") {
              return path.path;
            } else if (typeof path !== "string") {
              throw new qx.tool.cli.Utils.UserError("Cannot interpret configuration for libraries");
            }
            return path;
          });
        }
  
        if (!compileJson.defaultTarget) {
          const MAP_JOB_TO_TARGET = {
            "source": "source",
            "source-hybrid": "hybrid",
            "build": "build"
          };
          compileJson.defaultTarget = MAP_JOB_TO_TARGET[configJson["default-job"]]||"source";
        }
  
        var appName = getMacro("APPLICATION");
        var appClass = getMacro("APPLICATION_CLASS");
        if (!appClass) {
          appClass = appName + ".Application";
        }
        var qxTheme = getMacro("QXTHEME");
  
        t.debug(">>> Loading known library manifests");
        var libLookup = {};
  
        function addLibrary(ns, dir) {
          libLookup[ns] = {
            path: dir
          };
          compileJson.libraries.push(dir);
        }
  
        await Promise.all(compileJson.libraries.map(function(path) {
          return readFile(path + "/Manifest.json", {encoding: "utf8"})
            .then(function(data) {
              data = parseJson(data);
              var ns = data.provides.namespace;
              t.debug("    > Loaded " + ns);
              libLookup[ns] = {
                manifest: data,
                path: path
              };
            });
        }));
  
        if (configJson && configJson.jobs && configJson.libraries && configJson.libraries.library) {
          t.debug(">>> Loading extra library manifests");
          var all = configJson.libraries.library.map(async clib => {
            var filename = getMacro(clib.manifest);
            var pos = filename.lastIndexOf("/");
            var dir = filename.substring(pos + 1);
            var str = await readFile(filename, {encoding: "utf8"});
            var manifest = parseJson(str);
            var ns = manifest.provides.namespace;
            t.debug("    > Loaded " + ns);
            var lib = libLookup[ns];
            if (!lib) {
              addLibrary(ns, dir);
            }
          });
          await Promise.all(all);
        }
  
        this.info(">>> Configuring");
        if (!libLookup["qx"]) {
          var dir = getMacro("QOOXDOO_PATH");
          if (!dir) {
            throw new qx.tool.cli.Utils.UserError("Cannot find Qooxdoo in " + dir);
          } else {
            let p = path.join(dir, "framework");
            p = p.replace(/\\/g, "/");
            addLibrary("qx", p);
          }
        }
  
        if (appName.length && !libLookup[appName]) {
          addLibrary(appName, ".");
        }
  
        if (!compileJson.applications.length) {
          compileJson.applications.push({
            "class": appClass,
            theme: qxTheme,
            name: appName
          });
        }
  
        str = JsonToAst.reprint(compileJson, compileAst);
        await writeFile("compile.json", str, {encoding: "utf8"});
        this.info(">>> Done.");
      }
func_code_string: async function() {
        var t = this;
        var compileAst = null;
        var compileJson = {};
        var configJson;
  
        var lets = {};
        function getMacro(name) {
          var value = lets[name];
          value = replaceMacros(value);
          return value;
        }
  
        function replaceMacros(value) {
          if (!value) {
            return "";
          }
          // eslint-disable-next-line no-constant-condition
          while (true) {
            var pos = value.indexOf("${");
            var endPos = value.indexOf("}", pos);
            if (pos < 0 || endPos < 0) {
              return value;
            }
            var name = value.substring(pos + 2, endPos);
            var left = value.substring(0, pos);
            var right = value.substring(endPos + 1);
            value = left + lets[name] + right;
          }
        }
  
        function parseJson(str) {
          var ast = JsonToAst.parseToAst(str);
          var json = JsonToAst.astToObject(ast);
          return json;
        }
  
        t.debug(">>> Loading config.json");
        var data;
        try {
          data = await readFile("config.json", {encoding: "utf8"});
        } catch (ex) {
          if (ex.code == "ENOENT") {
            return;
          }
          throw new qx.tool.cli.Utils.UserError("Cannot read config.json: " + (ex.message||ex.stack));
        }
        try {
          configJson = parseJson(data);
        } catch (ex) {
          throw new qx.tool.cli.Utils.UserError("Cannot parse config.json: " + (ex.message||ex.stack));
        }
  
        t.debug(">>> Loading compile.json (if there is one)");
        try {
          data = await readFile("compile.json", {encoding: "utf8"});
          try {
            compileAst = JsonToAst.parseToAst(data, {verbose: true});
            compileJson = JsonToAst.astToObject(compileAst);
          } catch (ex) {
            throw new qx.tool.cli.Utils.UserError("Cannot parse compile.json: " + (ex.message||ex.stack));
          }
        } catch (err) {
          if (err.code !== "ENOENT") {
            throw err;
          }
        }
  
        t.debug(">>> Loading Manifest.json");
        try {
          var str = await readFile("Manifest.json", {encoding: "utf8"});
          data = parseJson(str);
        } catch (ex) {
          data = null;
        }
  
        lets = (configJson && configJson["let"])||{};
        compileJson = Object.assign({
          applications: [],
          libraries: [],
          targets: [
            {
              "type": "source",
              "outputPath": "compiled/source"
            },
            {
              "type": "build",
              "outputPath": "compiled/build"
            }
          ],
          defaultTarget: "source",
          locales: getMacro("LOCALES")|| ["en"]
        }, compileJson);
  
        if (compileJson.libraries) {
          compileJson.libraries = compileJson.libraries.map(function(path) {
            if (typeof path === "object" && typeof path.path === "string") {
              return path.path;
            } else if (typeof path !== "string") {
              throw new qx.tool.cli.Utils.UserError("Cannot interpret configuration for libraries");
            }
            return path;
          });
        }
  
        if (!compileJson.defaultTarget) {
          const MAP_JOB_TO_TARGET = {
            "source": "source",
            "source-hybrid": "hybrid",
            "build": "build"
          };
          compileJson.defaultTarget = MAP_JOB_TO_TARGET[configJson["default-job"]]||"source";
        }
  
        var appName = getMacro("APPLICATION");
        var appClass = getMacro("APPLICATION_CLASS");
        if (!appClass) {
          appClass = appName + ".Application";
        }
        var qxTheme = getMacro("QXTHEME");
  
        t.debug(">>> Loading known library manifests");
        var libLookup = {};
  
        function addLibrary(ns, dir) {
          libLookup[ns] = {
            path: dir
          };
          compileJson.libraries.push(dir);
        }
  
        await Promise.all(compileJson.libraries.map(function(path) {
          return readFile(path + "/Manifest.json", {encoding: "utf8"})
            .then(function(data) {
              data = parseJson(data);
              var ns = data.provides.namespace;
              t.debug("    > Loaded " + ns);
              libLookup[ns] = {
                manifest: data,
                path: path
              };
            });
        }));
  
        if (configJson && configJson.jobs && configJson.libraries && configJson.libraries.library) {
          t.debug(">>> Loading extra library manifests");
          var all = configJson.libraries.library.map(async clib => {
            var filename = getMacro(clib.manifest);
            var pos = filename.lastIndexOf("/");
            var dir = filename.substring(pos + 1);
            var str = await readFile(filename, {encoding: "utf8"});
            var manifest = parseJson(str);
            var ns = manifest.provides.namespace;
            t.debug("    > Loaded " + ns);
            var lib = libLookup[ns];
            if (!lib) {
              addLibrary(ns, dir);
            }
          });
          await Promise.all(all);
        }
  
        this.info(">>> Configuring");
        if (!libLookup["qx"]) {
          var dir = getMacro("QOOXDOO_PATH");
          if (!dir) {
            throw new qx.tool.cli.Utils.UserError("Cannot find Qooxdoo in " + dir);
          } else {
            let p = path.join(dir, "framework");
            p = p.replace(/\\/g, "/");
            addLibrary("qx", p);
          }
        }
  
        if (appName.length && !libLookup[appName]) {
          addLibrary(appName, ".");
        }
  
        if (!compileJson.applications.length) {
          compileJson.applications.push({
            "class": appClass,
            theme: qxTheme,
            name: appName
          });
        }
  
        str = JsonToAst.reprint(compileJson, compileAst);
        await writeFile("compile.json", str, {encoding: "utf8"});
        this.info(">>> Done.");
      }
func_documentation_string: /*
  @Override