zulip/tools
Anders Kaseorg 02511bff1c js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.

import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";

const checkExpression = (node: n.Node): node is K.ExpressionKind =>
  n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
  n.Statement.check(node);

for (const file of process.argv.slice(2)) {
  console.log("Parsing", file);
  const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
    parser: path.extname(file) === ".ts" ? tsParser : babelParser,
  });
  let changed = false;
  let inLoop = false;
  let replaceReturn = false;

  const visitLoop = (...args: string[]) =>
    function(this: Context, path: NodePath) {
      for (const arg of args) {
        this.visit(path.get(arg));
      }
      const old = { inLoop };
      inLoop = true;
      this.visit(path.get("body"));
      inLoop = old.inLoop;
      return false;
    };

  recast.visit(ast, {
    visitDoWhileStatement: visitLoop("test"),

    visitExpressionStatement(path) {
      const { expression, comments } = path.node;
      let valueOnly;
      if (
        n.CallExpression.check(expression) &&
        n.MemberExpression.check(expression.callee) &&
        !expression.callee.computed &&
        n.Identifier.check(expression.callee.object) &&
        expression.callee.object.name === "_" &&
        n.Identifier.check(expression.callee.property) &&
        ["each", "forEach"].includes(expression.callee.property.name) &&
        [2, 3].includes(expression.arguments.length) &&
        checkExpression(expression.arguments[0]) &&
        (n.FunctionExpression.check(expression.arguments[1]) ||
          n.ArrowFunctionExpression.check(expression.arguments[1])) &&
        [1, 2].includes(expression.arguments[1].params.length) &&
        n.Identifier.check(expression.arguments[1].params[0]) &&
        ((valueOnly = expression.arguments[1].params[1] === undefined) ||
          n.Identifier.check(expression.arguments[1].params[1])) &&
        (expression.arguments[2] === undefined ||
          n.ThisExpression.check(expression.arguments[2]))
      ) {
        const old = { inLoop, replaceReturn };
        inLoop = false;
        replaceReturn = true;
        this.visit(
          path
            .get("expression")
            .get("arguments")
            .get(1)
            .get("body")
        );
        inLoop = old.inLoop;
        replaceReturn = old.replaceReturn;

        const [right, { body, params }] = expression.arguments;
        const loop = b.forOfStatement(
          b.variableDeclaration("let", [
            b.variableDeclarator(
              valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
            ),
          ]),
          valueOnly
            ? right
            : b.callExpression(
                b.memberExpression(right, b.identifier("entries")),
                []
              ),
          checkStatement(body) ? body : b.expressionStatement(body)
        );
        loop.comments = comments;
        path.replace(loop);
        changed = true;
      }
      this.traverse(path);
    },

    visitForStatement: visitLoop("init", "test", "update"),

    visitForInStatement: visitLoop("left", "right"),

    visitForOfStatement: visitLoop("left", "right"),

    visitFunction(path) {
      this.visit(path.get("params"));
      const old = { replaceReturn };
      replaceReturn = false;
      this.visit(path.get("body"));
      replaceReturn = old.replaceReturn;
      return false;
    },

    visitReturnStatement(path) {
      if (replaceReturn) {
        assert(!inLoop); // could use labeled continue if this ever fires
        const { argument, comments } = path.node;
        if (argument === null) {
          const s = b.continueStatement();
          s.comments = comments;
          path.replace(s);
        } else {
          const s = b.expressionStatement(argument);
          s.comments = comments;
          path.replace(s, b.continueStatement());
        }
        return false;
      }
      this.traverse(path);
    },

    visitWhileStatement: visitLoop("test"),
  });

  if (changed) {
    console.log("Writing", file);
    fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
  }
}

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
..
ci dependencies: Remove WebSockets system for sending messages. 2020-01-14 22:34:00 -08:00
circleci requirements: Remove django-pipeline. 2019-07-24 17:40:31 -07:00
documentation_crawler docs: Deal with a few broken links. 2019-10-15 14:03:53 -07:00
droplets droplets: Update snapshot id. 2019-06-14 15:49:56 -07:00
i18n mypy: Upgrade from 0.720 to 0.730. 2019-11-13 12:38:45 -08:00
lib template_parser: Fix Jinja2 tag matching with strip whitespace syntax. 2020-01-16 12:53:34 -08:00
linter_lib check-openapi: Fix lint errors and remove lint exclusion. 2020-02-07 14:09:47 -08:00
setup setup_venv: Replace virtualenv_args list with python2 bool. 2020-02-05 12:38:10 -08:00
test-install test-install: Use lxc-destroy -f instead of lxc-stop. 2019-12-18 03:48:39 -08:00
tests template_parser: Fix Jinja2 tag matching with strip whitespace syntax. 2020-01-16 12:53:34 -08:00
zulip-export python: Migrate open statements to use with. 2019-07-20 15:48:52 -07:00
__init__.py Add __init__.py to tools/ and tools/setup/. 2016-07-20 18:20:37 -07:00
build-docs docs: Replace Makefile based on output of newer sphinx-quickstart. 2019-12-02 18:39:33 -08:00
build-release-tarball build-release-tarball: Run with zulip-py-venv symlink present. 2019-07-21 18:43:52 -07:00
cache-zulip-git-version version: Only let git describe match tags beginning with a digit. 2019-10-24 14:54:45 -07:00
check-capitalization i18n: Move static/locale back to locale. 2019-07-02 14:57:55 -07:00
check-frontend-i18n i18n: Move static/locale back to locale. 2019-07-02 14:57:55 -07:00
check-issue-labels lint: Fix code that evaded our lint checks for string % non-tuple. 2019-04-23 15:21:37 -07:00
check-openapi js: Automatically convert _.each to for…of. 2020-02-07 14:09:47 -08:00
check-provision tools: Extract get_provisioning_status check logic. 2019-06-23 21:55:02 -07:00
check-templates linter_lib: Fix mypy errors. 2019-08-09 17:22:45 -07:00
clean-branches clean-branches: Fix shellcheck warnings. 2018-10-17 17:38:56 -07:00
clean-repo clean-repo: Revert optimization to .pyc removal. 2017-07-30 17:24:55 -07:00
commit-message-lint commit-message-lint: Detect the upstream remote name. 2020-02-04 13:57:51 -08:00
commit-msg Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
conf.ini-template Add tool for scanning issues without area labels. 2017-02-03 09:59:35 -08:00
coveragerc request: Tighten type checking on REQ. 2019-11-13 12:35:55 -08:00
create-test-api-docs tools: Remove unused imports. 2019-02-02 17:10:31 -08:00
deploy-branch Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
diagnose typing: Remove now-unnecessary conditional import. 2019-07-29 15:18:22 -07:00
django-template-graph django-template-graph: Fix shellcheck warnings. 2018-10-17 17:38:56 -07:00
do-destroy-rebuild-database flush-memcached: Respect MEMCACHED_LOCATION; handle errors. 2019-10-01 16:05:55 -07:00
do-destroy-rebuild-test-database do-destroy-rebuild-test-database: Fix shellcheck warnings. 2018-08-03 09:15:26 -07:00
documentation.vnufilter test-documentation: Validate HTML with vnu.jar. 2019-06-27 14:53:21 -07:00
fetch-pull-request Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
fetch-rebase-pull-request Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
find-unused-css Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
get-handlebar-vars python: Migrate open statements to use with. 2019-07-20 15:48:52 -07:00
html-grep templates: Rename *.handlebars ↦ *.hbs and - ↦ _. 2019-07-12 21:11:03 -07:00
js-dep-visualizer.py tools: Add TypeScript to the dependency visualizer. 2019-04-12 11:14:42 -07:00
lint tools: Remove find-add-class tool. 2020-01-14 15:45:49 -08:00
pre-commit lint: Add --skip arg to replace --no-gitlint/mypy. 2019-06-18 11:32:04 -07:00
pretty-print-html python: Migrate open statements to use with. 2019-07-20 15:48:52 -07:00
provision install, provision: Treat all nonzero exit codes as failure, not just 1. 2019-07-19 11:22:11 -07:00
push-to-pull-request Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
README.md cleanup: Delete trailing newlines. 2019-08-06 23:29:11 -07:00
release-tarball-exclude.txt tests: Move zerver/fixtures to zerver/tests/fixtures for clarity. 2018-04-19 21:50:17 -07:00
renumber-migrations renumber-migrations: Exclude migration 0209. 2019-12-11 16:08:32 -08:00
replacer zulint: Move lister.py to tools/zulint. 2018-08-04 19:53:53 -07:00
reset-to-pull-request Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
review tools/review: Don’t pretend to emulate shell=True either. 2018-07-30 22:39:08 -07:00
run-dev.py dependencies: Remove WebSockets system for sending messages. 2020-01-14 22:34:00 -08:00
run-mypy lint: Run mypy with --no-error-summary. 2019-11-13 13:26:02 -08:00
run-tsc tsconfig: Move to top level. 2019-11-04 18:12:11 -08:00
run-yarn-deduplicate yarn.lock: Share duplicate packages with yarn-deduplicate. 2019-09-02 19:30:09 -07:00
setup-git-repo Use #!/usr/bin/env for bash shebangs. 2018-12-17 17:21:08 -08:00
show-profile-results mypy: Remove ignores for a few typeshed bugs fixed upstream. 2017-10-27 17:09:00 -07:00
stop-run-dev tools: Consistently use hyphen in user script names. 2017-10-11 12:52:36 -07:00
test-all lint: Use --groups to specify specific groups to run. 2019-06-23 22:23:15 -07:00
test-api api: Return a JsonableError if API key of invalid format is given. 2020-01-03 16:56:42 -08:00
test-backend populate_db: Extract some functions to server_initialization.py. 2020-01-29 17:26:45 -08:00
test-documentation test-documentation: Invoke sphinx-build via make instead of directly. 2019-12-02 18:39:33 -08:00
test-emoji-name-scripts test-emoji-name-scripts: Avoid hardcoded paths in /var/tmp. 2019-01-15 16:05:50 -08:00
test-help-documentation test-help-documentation: Bind vnu.jar to 127.0.0.1. 2019-06-28 18:18:29 -07:00
test-js-with-casper casper: Rename frontend_tests/run to clarify it uses casper. 2015-10-28 10:11:47 -07:00
test-js-with-node pm_list: Simplify redraws for Private Messages. 2020-01-30 13:11:32 -08:00
test-locked-requirements test-locked-requirements: Improve logged output. 2019-08-25 15:03:20 -07:00
test-migrations requirements: Upgrade django-otp from 0.5.2 to 0.6.0. 2019-07-07 22:28:54 -07:00
test-queue-worker-reload queue: Remove missedmessage_email_senders. 2020-01-31 12:13:51 -08:00
test-run-dev mypy: Upgrade from 0.720 to 0.730. 2019-11-13 12:38:45 -08:00
test-tools tools: Revert to Python 2 typing syntax for now. 2017-12-13 10:38:15 -08:00
update-authors-json update-authors-json: Clean up type ignores. 2019-08-09 16:39:16 -07:00
update-locked-requirements requirements: Fork pip.txt to pip2.txt for Python 2. 2020-02-05 12:38:10 -08:00
update-prod-static scripts: Move inline-email-css from tools to scripts. 2019-11-15 17:39:42 -08:00
update-zuliprc-api-field tools: Add tool to update API field of local zuliprc file. 2019-07-17 16:00:21 -07:00
webpack webpack: Enable code splitting and deduplication. 2019-10-28 15:53:15 -07:00
webpack-helpers.ts js: Automatically convert var to let and const in more files. 2019-11-20 14:10:47 -08:00
webpack.assets.json bundles: Factor out portico bundle. 2019-10-28 15:53:15 -07:00
webpack.config.ts js: Automatically convert var to let and const in more files. 2019-11-20 14:10:47 -08:00
zanitizer docs: Avoid hardcoded /tmp paths in miscellaneous documentation. 2019-01-15 16:16:12 -08:00
zanitizer_config.pm.sample zanitizer_config.pm.sample: keep_file → scrub_filename 2018-09-23 20:42:27 -07:00

This directory contains scripts that are used in building, managing, testing, and other forms of work in a Zulip development environment. Note that tools that are also useful in production belong in scripts/ or should be Django management commands.

For more details, see https://zulip.readthedocs.io/en/latest/overview/directory-structure.html.