From 897b58e6705c324bcc54fa55d200a6a0b3423699 Mon Sep 17 00:00:00 2001 From: Dmitrii Filippov Date: Wed, 20 May 2020 18:32:26 +0200 Subject: [PATCH] Add typescript compiler and use a separate folder as outdur This change adds typescript compilation step to the polygerrit build rules. The compiler is used only to produce the final gr-app bundle and is not used in other parts (tests, local development). In this change, the compiler does almost nothing - it only copies .js files to the output directory and makes some minor checks in .js files. Additionally, in this change the .ts-out directory as added to the top level of gerrit project. This directory is used as output directory when typescript runs in IDE. It is not used in bazel. Change-Id: I494993fd2ec98df45f46126399c2ee98c8365a2e --- .gitignore | 2 + .ts-out/README.md | 4 ++ polygerrit-ui/.gitignore | 2 +- polygerrit-ui/README.md | 21 ++++++ polygerrit-ui/app/BUILD | 40 ++++++++---- .../app/node_modules_licenses/tsconfig.json | 2 +- polygerrit-ui/app/rules.bzl | 65 +++++++++++++++++++ polygerrit-ui/app/tsconfig.json | 61 +++++++++++++++++ tools/node_tools/BUILD | 9 +++ .../node_modules_licenses/tsconfig.json | 2 +- tools/node_tools/utils/tsconfig.json | 2 +- 11 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 .ts-out/README.md create mode 100644 polygerrit-ui/app/tsconfig.json diff --git a/.gitignore b/.gitignore index bcafbb470373..8a41786f6ed1 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ !/plugins/webhooks /test_site /tools/format +/.ts-out/* +!/.ts-out/README.md diff --git a/.ts-out/README.md b/.ts-out/README.md new file mode 100644 index 000000000000..dada30d249b7 --- /dev/null +++ b/.ts-out/README.md @@ -0,0 +1,4 @@ +This directory contains compiled js code. Typescript uses subdirectories +as output directories when runs under IDE. + +Bazel doesn't use this directory diff --git a/polygerrit-ui/.gitignore b/polygerrit-ui/.gitignore index 7f06bef65bc3..7b33a5939fe8 100644 --- a/polygerrit-ui/.gitignore +++ b/polygerrit-ui/.gitignore @@ -4,4 +4,4 @@ dist fonts bower_components .tmp -.vscode \ No newline at end of file +.vscode diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md index 545c23873545..3b6f2ca877ef 100644 --- a/polygerrit-ui/README.md +++ b/polygerrit-ui/README.md @@ -1,5 +1,12 @@ # Gerrit Polymer Frontend +**Warning**: DON'T ADD MORE TYPESCRIPT FILES/TYPES. Gerrit Polymer Frontend +contains several typescript files and uses typescript compiler. This is a +preparation for the upcoming migration to typescript and we actively working on +it. We want to avoid massive typescript-related changes until the preparation +work is done. Thanks for your understanding! + + Follow the [setup instructions for Gerrit backend developers](https://gerrit-review.googlesource.com/Documentation/dev-readme.html) where applicable, the most important command is: @@ -74,6 +81,20 @@ bazel fetch @tools_npm//:node_modules More information for installing and using nodejs rules can be found here https://bazelbuild.github.io/rules_nodejs/install.html +## Setup typescript support in the IDE + +Modern IDE should automatically handle typescript settings from the +`pollygerrit-ui/app/tsconfig.json` files. IDE places compiled files in the +`.ts-out/pg` directory at the root of gerrit workspace and you can configure IDE +to exclude the whole .ts-out directory. To do it in the IntelliJ IDEA click on +this directory and select "Mark Directory As > Excluded" in the context menu. + +However, if you receive some errors from IDE, you can try to configure IDE +manually. For example, if IntelliJ IDEA shows +`Cannot find parent 'tsconfig.json'` error, you can try to setup typescript +options `--project polygerrit-ui/app/tsconfig.json` in the IDE settings. + + ## Serving files locally #### Go server diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD index 88e083488077..efacb47ae99e 100644 --- a/polygerrit-ui/app/BUILD +++ b/polygerrit-ui/app/BUILD @@ -1,24 +1,42 @@ -load(":rules.bzl", "polygerrit_bundle") +load(":rules.bzl", "compile_ts", "polygerrit_bundle") load("//tools/js:eslint.bzl", "eslint") package(default_visibility = ["//visibility:public"]) -polygerrit_bundle( - name = "polygerrit_ui", +# This list must be in sync with the "include" list in the tsconfig.json file +src_dirs = [ + "behaviors", + "constants", + "elements", + "embed", + "gr-diff", + "samples", + "scripts", + "services", + "styles", + "types", + "utils", +] + +compiled_pg_srcs = compile_ts( + name = "compile_pg", srcs = glob( - [ - "**/*.js", - ], + [src_dir + "/**/*" + ext for src_dir in src_dirs for ext in [ + ".js", + ".ts", + ]], exclude = [ - "node_modules/**", - "node_modules_licenses/**", - "test/**", - "**/*_test.html", "**/*_test.js", ], ), + ts_outdir = "_pg_ts_out", +) + +polygerrit_bundle( + name = "polygerrit_ui", + srcs = compiled_pg_srcs, outs = ["polygerrit_ui.zip"], - entry_point = "elements/gr-app.js", + entry_point = "_pg_ts_out/elements/gr-app.js", ) filegroup( diff --git a/polygerrit-ui/app/node_modules_licenses/tsconfig.json b/polygerrit-ui/app/node_modules_licenses/tsconfig.json index 6f4254f746b9..c562a0c932ed 100644 --- a/polygerrit-ui/app/node_modules_licenses/tsconfig.json +++ b/polygerrit-ui/app/node_modules_licenses/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "strict": true, "moduleResolution": "node", - "outDir": "out", + "outDir": "../../../.ts-out/polygerrit-ui/node_modules_licenses", // Not used in bazel "types": ["node"] }, "include": ["**/*.ts"] diff --git a/polygerrit-ui/app/rules.bzl b/polygerrit-ui/app/rules.bzl index 1492ad8bc9fc..74b9ac191a11 100644 --- a/polygerrit-ui/app/rules.bzl +++ b/polygerrit-ui/app/rules.bzl @@ -1,6 +1,71 @@ load("//tools/bzl:genrule2.bzl", "genrule2") load("@npm_bazel_rollup//:index.bzl", "rollup_bundle") +def _get_ts_compiled_path(outdir, file_name): + """Calculates the typescript output path for a file_name. + + Args: + outdir: the typescript output directory (relative to polygerrit-ui/app/) + file_name: the original file name (relative to polygerrit-ui/app/) + + Returns: + String - the path to the file produced by the typescript compiler + """ + if file_name.endswith(".js"): + return outdir + "/" + file_name + if file_name.endswith(".ts"): + return outdir + "/" + file_name[:-2] + "js" + fail("The file " + file_name + " has unsupported extension") + +def _get_ts_output_files(outdir, srcs): + """Calculates the files paths produced by the typescript compiler + + Args: + outdir: the typescript output directory (relative to polygerrit-ui/app/) + srcs: list of input files (all paths relative to polygerrit-ui/app/) + + Returns: + List of strings + """ + result = [] + for f in srcs: + if f.endswith(".d.ts"): + continue + result.append(_get_ts_compiled_path(outdir, f)) + return result + +def compile_ts(name, srcs, ts_outdir): + """Compiles srcs files with the typescript compiler + + Args: + name: rule name + srcs: list of input files (.js, .d.ts and .ts) + ts_outdir: typescript output directory + + Returns: + The list of compiled files + """ + ts_rule_name = name + "_ts_compiled" + + # List of files produced by the typescript compiler + generated_js = _get_ts_output_files(ts_outdir, srcs) + + # Run the compiler + native.genrule( + name = ts_rule_name, + srcs = srcs + [ + ":tsconfig.json", + "@ui_npm//:node_modules", + ], + outs = generated_js, + cmd = " && ".join([ + "$(location //tools/node_tools:tsc-bin) --project $(location :tsconfig.json) --outdir $(RULEDIR)/" + ts_outdir + " --baseUrl ./external/ui_npm/node_modules", + ]), + tools = ["//tools/node_tools:tsc-bin"], + ) + + return generated_js + def polygerrit_bundle(name, srcs, outs, entry_point): """Build .zip bundle from source code diff --git a/polygerrit-ui/app/tsconfig.json b/polygerrit-ui/app/tsconfig.json new file mode 100644 index 000000000000..e08621f681bd --- /dev/null +++ b/polygerrit-ui/app/tsconfig.json @@ -0,0 +1,61 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ + "module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "checkJs": false, /* Report errors in .js files. */ + "declaration": false, /* Temporary disabled - generates corresponding '.d.ts' file. */ + "declarationMap": false, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + "outDir": "../../.ts-out/polygerrit-ui/app", /* Not used in bazel. Redirect output structure to the directory. */ + "rootDir": ".", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "removeComments": false, /* Emit comments to output*/ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* Enable strict null checks. */ + "strictFunctionTypes": true, /* Enable strict checking of function types. */ + "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + + /* Additional Checks */ + "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true,/* Report errors for fallthrough cases in switch statement. */ + + "skipLibCheck": true, /* Do not check node_modules */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Advanced Options */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + "incremental": true + }, + // With the * pattern (without an extension), only supported files + // are included. The supported files are .ts, .tsx, .d.ts. + // If allowJs is set to true, .js and .jsx files are included as well. + // Note: gerrit doesn't have .tsx and .jsx files + "include": [ + // This items below must be in sync with the src_dirs list in the BUILD file + "behaviors/**/*", + "constants/**/*", + "elements/**/*", + "embed/**/*", + "gr-diff/**/*", + "samples/**/*", + "scripts/**/*", + "services/**/*", + "styles/**/*", + "types/**/*", + "utils/**/*", + // Directory for test utils (not included in src_dirs in the BUILD file) + "test/**/*" + ] +} diff --git a/tools/node_tools/BUILD b/tools/node_tools/BUILD index 4019542b1c4d..03e3a13c534f 100644 --- a/tools/node_tools/BUILD +++ b/tools/node_tools/BUILD @@ -36,3 +36,12 @@ nodejs_binary( # ts service in background). It works without any workaround. entry_point = "@tools_npm//:node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js", ) + +# Wrap a typescript into a tsc-bin binary. +# The tsc-bin can be used as a tool to compile typescript code. +nodejs_binary( + name = "tsc-bin", + # Point bazel to your node_modules to find the entry point + data = ["@tools_npm//:node_modules"], + entry_point = "@tools_npm//:node_modules/typescript/lib/tsc.js", +) diff --git a/tools/node_tools/node_modules_licenses/tsconfig.json b/tools/node_tools/node_modules_licenses/tsconfig.json index 28548575fcf8..2046c39403c7 100644 --- a/tools/node_tools/node_modules_licenses/tsconfig.json +++ b/tools/node_tools/node_modules_licenses/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "strict": true, "moduleResolution": "node", - "outDir": "out", + "outDir": "../../../.ts-out/tools/node_modules_licenses", // Not used in bazel, "types": ["node"] }, "include": ["*.ts"] diff --git a/tools/node_tools/utils/tsconfig.json b/tools/node_tools/utils/tsconfig.json index 34ffb2fd1ac4..56ab91b0235f 100644 --- a/tools/node_tools/utils/tsconfig.json +++ b/tools/node_tools/utils/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "strict": true, "moduleResolution": "node", - "outDir": "out" + "outDir": "../../../.ts-out/tools/utils" // Not used in bazel }, "include": ["*.ts"] }