From 11f12ac501290f9f79ac61925c92857952c269bd Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Mon, 14 Jan 2019 23:04:07 +0900 Subject: [PATCH] refactor: rewrite tools/format.py in deno Note: findFiles and findFilesWalk are borrowed from the previous attempt of @pseudo-su (#1434). Thanks! --- .github/CONTRIBUTING.md | 2 +- .travis.yml | 2 +- Docs.md | 2 +- js/unit_tests.ts | 2 + tools/format.py | 50 ------------ tools/format.ts | 78 +++++++++++++++++++ tools/test_format.py | 28 ++++++- tools/testdata/find_files_testdata/bar.md | 1 + tools/testdata/find_files_testdata/bar.ts | 1 + tools/testdata/find_files_testdata/bar.txt | 1 + tools/testdata/find_files_testdata/foo.md | 1 + tools/testdata/find_files_testdata/foo.ts | 1 + tools/testdata/find_files_testdata/foo.txt | 1 + .../find_files_testdata/subdir0/bar.ts | 1 + .../find_files_testdata/subdir0/foo.ts | 1 + .../subdir0/subdir0/bar.ts | 1 + .../subdir0/subdir0/foo.ts | 1 + .../find_files_testdata/subdir1/bar.ts | 1 + .../find_files_testdata/subdir1/foo.ts | 1 + tools/util.ts | 40 ++++++++++ tools/util_test.ts | 49 ++++++++++++ 21 files changed, 209 insertions(+), 56 deletions(-) delete mode 100755 tools/format.py create mode 100755 tools/format.ts create mode 100644 tools/testdata/find_files_testdata/bar.md create mode 100644 tools/testdata/find_files_testdata/bar.ts create mode 100644 tools/testdata/find_files_testdata/bar.txt create mode 100644 tools/testdata/find_files_testdata/foo.md create mode 100644 tools/testdata/find_files_testdata/foo.ts create mode 100644 tools/testdata/find_files_testdata/foo.txt create mode 100644 tools/testdata/find_files_testdata/subdir0/bar.ts create mode 100644 tools/testdata/find_files_testdata/subdir0/foo.ts create mode 100644 tools/testdata/find_files_testdata/subdir0/subdir0/bar.ts create mode 100644 tools/testdata/find_files_testdata/subdir0/subdir0/foo.ts create mode 100644 tools/testdata/find_files_testdata/subdir1/bar.ts create mode 100644 tools/testdata/find_files_testdata/subdir1/foo.ts create mode 100644 tools/util.ts create mode 100644 tools/util_test.ts diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c862484f99f9ed..e2965ac95e218c 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -18,7 +18,7 @@ Docs are [here](https://github.com/denoland/deno/blob/master/Docs.md). Before submitting, please make sure the following is done: 1. Ensure `./tools/test.py` passes. -2. Format your code with `./tools/format.py`. +2. Format your code with `./tools/format.ts`. 3. Make sure `./tools/lint.py` passes. ## Changes to `third_party` diff --git a/.travis.yml b/.travis.yml index 50fd8c8acd435c..777fb047843349 100644 --- a/.travis.yml +++ b/.travis.yml @@ -63,8 +63,8 @@ before_script: # Default script for release builds. script: - ./tools/lint.py -- ./tools/test_format.py - ./tools/build.py -C target/release +- ./tools/test_format.py - DENO_BUILD_MODE=release ./tools/test.py jobs: diff --git a/Docs.md b/Docs.md index 15a59ad436e337..4d40103863a8b0 100644 --- a/Docs.md +++ b/Docs.md @@ -344,7 +344,7 @@ submodule. However, you need to install separately: ./tools/test.py # Format code. - ./tools/format.py + ./tools/format.ts Other useful commands: diff --git a/js/unit_tests.ts b/js/unit_tests.ts index e02d5e303761bc..9b6ce3592c00e3 100644 --- a/js/unit_tests.ts +++ b/js/unit_tests.ts @@ -41,4 +41,6 @@ import "./url_test.ts"; import "./url_search_params_test.ts"; import "./write_file_test.ts"; +import "../tools/util_test.ts"; + import "../website/app_test.js"; diff --git a/tools/format.py b/tools/format.py deleted file mode 100755 index 79282618d7cb2d..00000000000000 --- a/tools/format.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# Copyright 2018 the Deno authors. All rights reserved. MIT license. -from glob import glob -import os -import sys -from third_party import fix_symlinks, google_env, python_env -from third_party import clang_format_path, third_party_path -from util import root_path, run, find_exts, platform - -fix_symlinks() - -prettier = os.path.join(third_party_path, "node_modules", "prettier", - "bin-prettier.js") -tools_path = os.path.join(root_path, "tools") -rustfmt_config = os.path.join(tools_path, "rustfmt.toml") - -os.chdir(root_path) - - -def qrun(cmd, env=None): - run(cmd, quiet=True, env=env) - - -print "clang_format" -qrun([clang_format_path, "-i", "-style", "Google"] + - find_exts(["libdeno"], [".cc", ".h"])) - -print "gn format" -for fn in ["BUILD.gn", ".gn"] + find_exts(["build_extra", "libdeno"], - [".gn", ".gni"]): - qrun(["third_party/depot_tools/gn", "format", fn], env=google_env()) - -print "yapf" -qrun( - [sys.executable, "third_party/python_packages/bin/yapf", "-i"] + find_exts( - ["tools", "build_extra"], [".py"], skip=["tools/clang"]), - env=python_env()) - -print "prettier" -qrun(["node", prettier, "--write", "--loglevel=error"] + ["rollup.config.js"] + - glob("*.json") + glob("*.md") + - find_exts([".github", "js", "tests", "tools", "website"], - [".js", ".json", ".ts", ".md"], - skip=["tools/clang", "js/deps"])) - -print "rustfmt" -qrun([ - "third_party/rustfmt/" + platform() + - "/rustfmt", "--config-path", rustfmt_config, "build.rs" -] + find_exts(["src"], [".rs"])) diff --git a/tools/format.ts b/tools/format.ts new file mode 100755 index 00000000000000..897c2f17688b04 --- /dev/null +++ b/tools/format.ts @@ -0,0 +1,78 @@ +#!/usr/bin/env deno --allow-run +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import * as deno from "deno"; +import { join } from "../js/deps/https/deno.land/x/std/path/index.ts"; +import { findFiles } from "./util.ts"; + +const clangFormat = join("third_party", "depot_tools", "clang-format"); +const gn = join("third_party", "depot_tools", "gn"); +const prettier = join( + "third_party", + "node_modules", + "prettier", + "bin-prettier.js" +); +const yapf = join("third_party", "python_packages", "bin", "yapf"); +const rustfmt = join("third_party", "rustfmt", deno.platform.os, "rustfmt"); +const rustfmtConfig = join("tools", "rustfmt.toml"); + +const run = (...args: string[]) => { + if (deno.platform.os === "win") { + args = ["cmd.exe", "/c", ...args]; + } + return deno.run({ args, stdout: "null", stderr: "piped" }).status(); +}; + +(async () => { + console.log("clang_format"); + await run( + clangFormat, + "-i", + "-style", + "Google", + ...findFiles(["libdeno"], [".cc", ".h"]) + ); + + console.log("gn format"); + for (const fn of [ + "BUILD.gn", + ".gn", + ...findFiles(["build_extra", "libdeno"], [".gn", ".gni"]) + ]) { + await run(gn, "format", fn); + } + + console.log("yapf"); + await run( + "python", + yapf, + "-i", + ...findFiles(["tools", "build_extra"], [".py"], { + skip: [join("tools", "clang")] + }) + ); + + console.log("prettier"); + await run( + "node", + prettier, + "--write", + "--loglevel=error", + "rollup.config.js", + ...findFiles(["."], [".json", ".md"], { depth: 1 }), + ...findFiles( + [".github", "js", "tests", "tools", "website"], + [".js", ".json", ".ts", ".md"], + { skip: [join("tools", "clang"), join("js", "deps")] } + ) + ); + + console.log("rustfmt"); + await run( + rustfmt, + "--config-path", + rustfmtConfig, + "build.rs", + ...findFiles(["src"], [".rs"]) + ); +})(); diff --git a/tools/test_format.py b/tools/test_format.py index a0d5ba08ec0541..8be990da4f8e64 100755 --- a/tools/test_format.py +++ b/tools/test_format.py @@ -1,18 +1,40 @@ #!/usr/bin/env python -# This program fails if ./tools/format.py changes any files. +# Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +# This program fails if ./tools/format.ts changes any files. +import os import sys import util import sys import subprocess +from distutils.spawn import find_executable +def lookup_deno_path(): + deno_exe = "deno" + util.executable_suffix + release_deno = os.path.join(root_path, "target", "release", deno_exe) + debug_deno = os.path.join(root_path, "target", "debug", deno_exe) + + if os.path.exists(release_deno): + return release_deno + if os.path.exists(debug_deno): + return debug_deno + + return find_executable("deno") + + def main(): - util.run([sys.executable, "tools/format.py"]) + deno_path = lookup_deno_path() + + if not deno_path: + print "No available deno executable." + sys.exit(1) + + util.run([deno_path, "--allow-run", "tools/format.ts"]) output = util.run_output( ["git", "status", "-uno", "--porcelain", "--ignore-submodules"]) if len(output) > 0: - print "Run tools/format.py " + print "Run tools/format.ts " print output sys.exit(1) diff --git a/tools/testdata/find_files_testdata/bar.md b/tools/testdata/find_files_testdata/bar.md new file mode 100644 index 00000000000000..d93e603dcdc15c --- /dev/null +++ b/tools/testdata/find_files_testdata/bar.md @@ -0,0 +1 @@ +# bar diff --git a/tools/testdata/find_files_testdata/bar.ts b/tools/testdata/find_files_testdata/bar.ts new file mode 100644 index 00000000000000..636c1fc2774efa --- /dev/null +++ b/tools/testdata/find_files_testdata/bar.ts @@ -0,0 +1 @@ +console.log("bar"); diff --git a/tools/testdata/find_files_testdata/bar.txt b/tools/testdata/find_files_testdata/bar.txt new file mode 100644 index 00000000000000..5716ca5987cbf9 --- /dev/null +++ b/tools/testdata/find_files_testdata/bar.txt @@ -0,0 +1 @@ +bar diff --git a/tools/testdata/find_files_testdata/foo.md b/tools/testdata/find_files_testdata/foo.md new file mode 100644 index 00000000000000..c2a839280e2e96 --- /dev/null +++ b/tools/testdata/find_files_testdata/foo.md @@ -0,0 +1 @@ +# foo diff --git a/tools/testdata/find_files_testdata/foo.ts b/tools/testdata/find_files_testdata/foo.ts new file mode 100644 index 00000000000000..85ce559e8f22b7 --- /dev/null +++ b/tools/testdata/find_files_testdata/foo.ts @@ -0,0 +1 @@ +console.log("foo"); diff --git a/tools/testdata/find_files_testdata/foo.txt b/tools/testdata/find_files_testdata/foo.txt new file mode 100644 index 00000000000000..257cc5642cb1a0 --- /dev/null +++ b/tools/testdata/find_files_testdata/foo.txt @@ -0,0 +1 @@ +foo diff --git a/tools/testdata/find_files_testdata/subdir0/bar.ts b/tools/testdata/find_files_testdata/subdir0/bar.ts new file mode 100644 index 00000000000000..636c1fc2774efa --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir0/bar.ts @@ -0,0 +1 @@ +console.log("bar"); diff --git a/tools/testdata/find_files_testdata/subdir0/foo.ts b/tools/testdata/find_files_testdata/subdir0/foo.ts new file mode 100644 index 00000000000000..85ce559e8f22b7 --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir0/foo.ts @@ -0,0 +1 @@ +console.log("foo"); diff --git a/tools/testdata/find_files_testdata/subdir0/subdir0/bar.ts b/tools/testdata/find_files_testdata/subdir0/subdir0/bar.ts new file mode 100644 index 00000000000000..636c1fc2774efa --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir0/subdir0/bar.ts @@ -0,0 +1 @@ +console.log("bar"); diff --git a/tools/testdata/find_files_testdata/subdir0/subdir0/foo.ts b/tools/testdata/find_files_testdata/subdir0/subdir0/foo.ts new file mode 100644 index 00000000000000..85ce559e8f22b7 --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir0/subdir0/foo.ts @@ -0,0 +1 @@ +console.log("foo"); diff --git a/tools/testdata/find_files_testdata/subdir1/bar.ts b/tools/testdata/find_files_testdata/subdir1/bar.ts new file mode 100644 index 00000000000000..636c1fc2774efa --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir1/bar.ts @@ -0,0 +1 @@ +console.log("bar"); diff --git a/tools/testdata/find_files_testdata/subdir1/foo.ts b/tools/testdata/find_files_testdata/subdir1/foo.ts new file mode 100644 index 00000000000000..85ce559e8f22b7 --- /dev/null +++ b/tools/testdata/find_files_testdata/subdir1/foo.ts @@ -0,0 +1 @@ +console.log("foo"); diff --git a/tools/util.ts b/tools/util.ts new file mode 100644 index 00000000000000..5ff7da34456d66 --- /dev/null +++ b/tools/util.ts @@ -0,0 +1,40 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import { lstatSync, readDirSync } from "deno"; + +export interface FindOptions { + skip?: string[]; + depth?: number; +} + +/** + * Finds files of the give extensions under the given paths recursively. + * @param dirs directories + * @param exts extensions + * @param skip patterns to ignore + * @param depth depth to find + */ +export function findFiles( + dirs: string[], + exts: string[], + { skip = [], depth = 20 }: FindOptions = {} +) { + return findFilesWalk(dirs, depth).filter( + path => + exts.some(ext => path.endsWith(ext)) && + skip.every(pattern => !path.includes(pattern)) + ); +} + +function findFilesWalk(paths: string[], depth: number) { + if (depth < 0) { + return []; + } + + const foundPaths = paths.map(path => + lstatSync(path).isDirectory() + ? findFilesWalk(readDirSync(path).map(f => f.path), depth - 1) + : path + ); + + return [].concat(...foundPaths); +} diff --git a/tools/util_test.ts b/tools/util_test.ts new file mode 100644 index 00000000000000..79868b4401803e --- /dev/null +++ b/tools/util_test.ts @@ -0,0 +1,49 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import { test, assertEqual } from "../js/test_util.ts"; +import { findFiles } from "./util.ts"; + +const testDir = "tools/testdata/find_files_testdata"; + +// Sorts and replace backslashes with slashes. +const normalize = files => files.map(f => f.replace(/\\/g, "/")).sort(); + +test(function testFindFiles() { + const files = findFiles([testDir], [".ts", ".md"]); + assertEqual(normalize(files), [ + `${testDir}/bar.md`, + `${testDir}/bar.ts`, + `${testDir}/foo.md`, + `${testDir}/foo.ts`, + `${testDir}/subdir0/bar.ts`, + `${testDir}/subdir0/foo.ts`, + `${testDir}/subdir0/subdir0/bar.ts`, + `${testDir}/subdir0/subdir0/foo.ts`, + `${testDir}/subdir1/bar.ts`, + `${testDir}/subdir1/foo.ts` + ]); +}); + +test(function testFindFilesDepth() { + const files = findFiles([testDir], [".ts", ".md"], { depth: 1 }); + assertEqual(normalize(files), [ + `${testDir}/bar.md`, + `${testDir}/bar.ts`, + `${testDir}/foo.md`, + `${testDir}/foo.ts` + ]); +}); + +test(function testFindFilesSkip() { + const files = findFiles([testDir], [".ts", ".md"], { + skip: ["foo.md", "subdir1"] + }); + assertEqual(normalize(files), [ + `${testDir}/bar.md`, + `${testDir}/bar.ts`, + `${testDir}/foo.ts`, + `${testDir}/subdir0/bar.ts`, + `${testDir}/subdir0/foo.ts`, + `${testDir}/subdir0/subdir0/bar.ts`, + `${testDir}/subdir0/subdir0/foo.ts` + ]); +});