build: add bazel integration test (#18733)
It includes sass compilation, and building the bazel package distribution. PR Close #18733
This commit is contained in:
parent
9ffa490d3f
commit
47220997e1
|
@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
git_repository(
|
git_repository(
|
||||||
name = "build_bazel_rules_typescript",
|
name = "build_bazel_rules_typescript",
|
||||||
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||||
tag = "0.0.5",
|
tag = "0.0.6",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//:defs.bzl", "node_repositories")
|
load("@build_bazel_rules_typescript//:defs.bzl", "node_repositories")
|
||||||
|
|
31
build.sh
31
build.sh
|
@ -327,6 +327,16 @@ mapSources() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVersionReferences() {
|
||||||
|
NPM_DIR="$1"
|
||||||
|
(
|
||||||
|
echo "====== VERSION: Updating version references in ${NPM_DIR}"
|
||||||
|
cd ${NPM_DIR}
|
||||||
|
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
|
||||||
|
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
VERSION="${VERSION_PREFIX}${VERSION_SUFFIX}"
|
VERSION="${VERSION_PREFIX}${VERSION_SUFFIX}"
|
||||||
echo "====== BUILDING: Version ${VERSION}"
|
echo "====== BUILDING: Version ${VERSION}"
|
||||||
|
|
||||||
|
@ -419,11 +429,15 @@ if [[ ${BUILD_TOOLS} == true || ${BUILD_ALL} == true ]]; then
|
||||||
$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json
|
$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json
|
||||||
cp ./packages/tsc-wrapped/package.json ./dist/packages-dist/tsc-wrapped
|
cp ./packages/tsc-wrapped/package.json ./dist/packages-dist/tsc-wrapped
|
||||||
cp ./packages/tsc-wrapped/README.md ./dist/packages-dist/tsc-wrapped
|
cp ./packages/tsc-wrapped/README.md ./dist/packages-dist/tsc-wrapped
|
||||||
(
|
updateVersionReferences dist/packages-dist/tsc-wrapped
|
||||||
cd dist/packages-dist/tsc-wrapped
|
|
||||||
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
|
rsync -a packages/bazel/ ./dist/packages-dist/bazel
|
||||||
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
|
# Re-write nodejs import paths
|
||||||
)
|
perl -p -i -e "s#__main__/packages/bazel#angular#g" $(grep -ril __main__ dist/packages-dist/bazel) < /dev/null 2> /dev/null
|
||||||
|
# Remove BEGIN-INTERNAL...END-INTERAL blocks
|
||||||
|
# https://stackoverflow.com/questions/24175271/how-can-i-match-multi-line-patterns-in-the-command-line-with-perl-style-regex
|
||||||
|
perl -0777 -n -i -e "s/(?m)^.*BEGIN-INTERNAL[\w\W]*END-INTERNAL.*\n//g; print" $(grep -ril BEGIN-INTERNAL dist/packages-dist/bazel) < /dev/null 2> /dev/null
|
||||||
|
updateVersionReferences dist/packages-dist/bazel
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for PACKAGE in ${PACKAGES[@]}
|
for PACKAGE in ${PACKAGES[@]}
|
||||||
|
@ -489,12 +503,7 @@ do
|
||||||
|
|
||||||
|
|
||||||
if [[ -d ${NPM_DIR} ]]; then
|
if [[ -d ${NPM_DIR} ]]; then
|
||||||
(
|
updateVersionReferences ${NPM_DIR}
|
||||||
echo "====== VERSION: Updating version references"
|
|
||||||
cd ${NPM_DIR}
|
|
||||||
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
|
|
||||||
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
|
|
||||||
)
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
travisFoldEnd "build package: ${PACKAGE}"
|
travisFoldEnd "build package: ${PACKAGE}"
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "node_modules",
|
||||||
|
srcs = glob([
|
||||||
|
"node_modules/**/*.js",
|
||||||
|
"node_modules/**/*.d.ts",
|
||||||
|
"node_modules/**/*.json",
|
||||||
|
])
|
||||||
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
|
|
||||||
|
git_repository(
|
||||||
|
name = "build_bazel_rules_typescript",
|
||||||
|
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||||
|
tag = "0.0.6",
|
||||||
|
)
|
||||||
|
load("@build_bazel_rules_typescript//:defs.bzl", "node_repositories")
|
||||||
|
node_repositories(package_json = "//:package.json")
|
||||||
|
|
||||||
|
local_repository(
|
||||||
|
name = "angular",
|
||||||
|
path = "node_modules/@angular/bazel"
|
||||||
|
)
|
||||||
|
|
||||||
|
git_repository(
|
||||||
|
name = "io_bazel_rules_sass",
|
||||||
|
remote = "https://github.com/bazelbuild/rules_sass.git",
|
||||||
|
tag = "0.0.2",
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_repositories")
|
||||||
|
|
||||||
|
sass_repositories()
|
|
@ -0,0 +1,21 @@
|
||||||
|
// WORKAROUND https://github.com/angular/angular/issues/18810
|
||||||
|
// This file is required to run ngc on angular libraries, to write files like
|
||||||
|
// node_modules/@angular/core/core.ngsummary.json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"node_modules/@angular/**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules/@angular/bazel/**",
|
||||||
|
"node_modules/@angular/compiler-cli/**",
|
||||||
|
"node_modules/@angular/tsc-wrapped/**"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "angular-bazel",
|
||||||
|
"description": "example and integration test for building Angular apps with Bazel",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "file:../../dist/packages-dist/animations",
|
||||||
|
"@angular/common": "file:../../dist/packages-dist/common",
|
||||||
|
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||||
|
"@angular/core": "file:../../dist/packages-dist/core",
|
||||||
|
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
|
||||||
|
"rxjs": "5.3.1",
|
||||||
|
"zone.js": "0.8.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular/bazel": "file:../../dist/packages-dist/bazel",
|
||||||
|
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||||
|
"@types/node": "^7.0.18",
|
||||||
|
"protobufjs": "5.0.0",
|
||||||
|
"typescript": "~2.3.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "ngc -p angular.tsconfig.json",
|
||||||
|
"test": "bazel build ..."
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
load("@angular//:index.bzl", "ng_module")
|
||||||
|
|
||||||
|
# Allow targets under sub-packages to reference the tsconfig.json file
|
||||||
|
exports_files(["tsconfig.json"])
|
||||||
|
|
||||||
|
ng_module(
|
||||||
|
name = "app",
|
||||||
|
srcs = ["app.module.ts"],
|
||||||
|
deps = ["//src/hello-world"],
|
||||||
|
tsconfig = ":tsconfig.json",
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
import {HelloWorldModule} from './hello-world/hello-world.module';
|
||||||
|
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [BrowserModule, HelloWorldModule]
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
load("@angular//:index.bzl", "ng_module")
|
||||||
|
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_binary")
|
||||||
|
|
||||||
|
sass_binary(
|
||||||
|
name = "styles",
|
||||||
|
src = "hello-world.component.scss",
|
||||||
|
deps = [
|
||||||
|
"//src/shared:colors",
|
||||||
|
"//src/shared:fonts",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ng_module(
|
||||||
|
name = "hello-world",
|
||||||
|
srcs = glob(["*.ts"]),
|
||||||
|
tsconfig = "//src:tsconfig.json",
|
||||||
|
assets = [":styles"],
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
@import "src/shared/fonts";
|
||||||
|
@import "src/shared/colors";
|
||||||
|
|
||||||
|
html {
|
||||||
|
body {
|
||||||
|
font-family: $default-font-stack;
|
||||||
|
h1 {
|
||||||
|
font-family: $modern-font-stack;
|
||||||
|
color: $example-red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
import {Component, NgModule} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hello-world-app',
|
||||||
|
template: `
|
||||||
|
<div>Hello {{ name }}!</div>
|
||||||
|
<input type="text" [value]="name" (input)="name = $event.target.value"/>
|
||||||
|
`,
|
||||||
|
// TODO: might be better to point to .scss so this looks valid at design-time
|
||||||
|
styleUrls: ['./styles.css']
|
||||||
|
})
|
||||||
|
export class HelloWorldComponent {
|
||||||
|
name: string = 'world';
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {HelloWorldComponent} from './hello-world.component';
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [HelloWorldComponent],
|
||||||
|
bootstrap: [HelloWorldComponent],
|
||||||
|
})
|
||||||
|
export class HelloWorldModule {}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_library")
|
||||||
|
|
||||||
|
sass_library(
|
||||||
|
name = "colors",
|
||||||
|
srcs = ["_colors.scss"],
|
||||||
|
)
|
||||||
|
|
||||||
|
sass_library(
|
||||||
|
name = "fonts",
|
||||||
|
srcs = ["_fonts.scss"],
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
$example-blue: #0000ff;
|
||||||
|
$example-red: #ff0000;
|
|
@ -0,0 +1,2 @@
|
||||||
|
$default-font-stack: Cambria, "Hoefler Text", Utopia, "Liberation Serif", "Nimbus Roman No9 L Regular", Times, "Times New Roman", serif;
|
||||||
|
$modern-font-stack: Constantia, "Lucida Bright", Lucidabright, "Lucida Serif", Lucida, "DejaVu Serif", "Bitstream Vera Serif", "Liberation Serif", Georgia, serif;
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es5",
|
||||||
|
"es2015.collection",
|
||||||
|
"es2015.iterable",
|
||||||
|
"es2015.promise"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
git_repository(
|
git_repository(
|
||||||
name = "build_bazel_rules_typescript",
|
name = "build_bazel_rules_typescript",
|
||||||
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||||
tag = "0.0.5",
|
tag = "0.0.6",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//:defs.bzl", "node_repositories")
|
load("@build_bazel_rules_typescript//:defs.bzl", "node_repositories")
|
||||||
|
|
|
@ -3,72 +3,113 @@
|
||||||
# Use of this source code is governed by an MIT-style license that can be
|
# Use of this source code is governed by an MIT-style license that can be
|
||||||
# found in the LICENSE file at https://angular.io/license
|
# found in the LICENSE file at https://angular.io/license
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//internal:build_defs.bzl", "tsc_wrapped_tsconfig")
|
load(":rules_typescript.bzl",
|
||||||
|
"tsc_wrapped_tsconfig",
|
||||||
load(
|
"COMMON_ATTRIBUTES",
|
||||||
"@build_bazel_rules_typescript//internal:common/compilation.bzl",
|
"compile_ts",
|
||||||
"COMMON_ATTRIBUTES", "compile_ts", "ts_providers_dict_to_struct"
|
"DEPS_ASPECTS",
|
||||||
|
"ts_providers_dict_to_struct",
|
||||||
|
"json_marshal",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//internal:common/json_marshal.bzl", "json_marshal")
|
|
||||||
|
|
||||||
# Calculate the expected output of the template compiler for every source in
|
# Calculate the expected output of the template compiler for every source in
|
||||||
# in the library. Most of these will be produced as empty files but it is
|
# in the library. Most of these will be produced as empty files but it is
|
||||||
# unknown, without parsing, which will be empty.
|
# unknown, without parsing, which will be empty.
|
||||||
def _expected_outs(ctx):
|
def _expected_outs(ctx, label):
|
||||||
result = []
|
devmode_js_files = []
|
||||||
|
closure_js_files = []
|
||||||
|
declaration_files = []
|
||||||
|
summary_files = []
|
||||||
|
|
||||||
|
codegen_inputs = ctx.files.srcs
|
||||||
|
|
||||||
|
for src in ctx.files.srcs + ctx.files.assets:
|
||||||
|
if src.short_path.endswith(".ts") and not src.short_path.endswith(".d.ts"):
|
||||||
|
basename = src.short_path[len(ctx.label.package) + 1:-len(".ts")]
|
||||||
|
devmode_js = [
|
||||||
|
".ngfactory.js",
|
||||||
|
".ngsummary.js",
|
||||||
|
".js",
|
||||||
|
]
|
||||||
|
summaries = [".ngsummary.json"]
|
||||||
|
|
||||||
for src in ctx.files.srcs:
|
|
||||||
if src.short_path.endswith(".ts"):
|
|
||||||
basename = src.short_path[len(ctx.label.package) + 1:-3]
|
|
||||||
result += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in [
|
|
||||||
".ngfactory.js",
|
|
||||||
".ngfactory.d.ts",
|
|
||||||
".ngsummary.js",
|
|
||||||
".ngsummary.d.ts",
|
|
||||||
".ngsummary.json",
|
|
||||||
]]
|
|
||||||
elif src.short_path.endswith(".css"):
|
elif src.short_path.endswith(".css"):
|
||||||
basename = src.short_path[len(ctx.label.package) + 1:-4]
|
basename = src.short_path[len(ctx.label.package) + 1:-len(".css")]
|
||||||
result += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in [
|
devmode_js = [
|
||||||
".css.shim.ngstyle.js",
|
".css.shim.ngstyle.js",
|
||||||
".css.shim.ngstyle.d.ts",
|
".css.ngstyle.js",
|
||||||
".css.ngstyle.js",
|
]
|
||||||
".css.ngstyle.d.ts",
|
summaries = []
|
||||||
]]
|
|
||||||
return result
|
closure_js = [f.replace(".js", ".closure.js") for f in devmode_js]
|
||||||
|
declarations = [f.replace(".js", ".d.ts") for f in devmode_js]
|
||||||
|
|
||||||
|
devmode_js_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in devmode_js]
|
||||||
|
closure_js_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in closure_js]
|
||||||
|
declaration_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in declarations]
|
||||||
|
summary_files += [ctx.new_file(ctx.bin_dir, basename + ext) for ext in summaries]
|
||||||
|
|
||||||
|
return struct(
|
||||||
|
closure_js = closure_js_files,
|
||||||
|
devmode_js = devmode_js_files,
|
||||||
|
declarations = declaration_files,
|
||||||
|
summaries = summary_files,
|
||||||
|
)
|
||||||
|
|
||||||
def _ngc_tsconfig(ctx, files, srcs, **kwargs):
|
def _ngc_tsconfig(ctx, files, srcs, **kwargs):
|
||||||
|
outs = _expected_outs(ctx, ctx.label)
|
||||||
|
if "devmode_manifest" in kwargs:
|
||||||
|
expected_outs = outs.devmode_js + outs.declarations + outs.summaries
|
||||||
|
else:
|
||||||
|
expected_outs = outs.closure_js
|
||||||
|
|
||||||
return dict(tsc_wrapped_tsconfig(ctx, files, srcs, **kwargs), **{
|
return dict(tsc_wrapped_tsconfig(ctx, files, srcs, **kwargs), **{
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
"expectedOut": [o.path for o in _expected_outs(ctx)],
|
"generateCodeForLibraries": False,
|
||||||
|
# FIXME: wrong place to de-dupe
|
||||||
|
"expectedOut": depset([o.path for o in expected_outs]).to_list()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def _collect_summaries_aspect_impl(target, ctx):
|
||||||
|
results = target.angular.summaries if hasattr(target, "angular") else depset()
|
||||||
|
|
||||||
|
# If we are visiting empty-srcs ts_library, this is a re-export
|
||||||
|
srcs = target.srcs if hasattr(target, "srcs") else []
|
||||||
|
|
||||||
|
# "re-export" rules should expose all the files of their deps
|
||||||
|
if not srcs:
|
||||||
|
for dep in ctx.rule.attr.deps:
|
||||||
|
if (hasattr(dep, "angular")):
|
||||||
|
results += dep.angular.summaries
|
||||||
|
|
||||||
|
return struct(collect_summaries_aspect_result = results)
|
||||||
|
|
||||||
|
_collect_summaries_aspect = aspect(
|
||||||
|
implementation = _collect_summaries_aspect_impl,
|
||||||
|
attr_aspects = ["deps"],
|
||||||
|
)
|
||||||
|
|
||||||
def _compile_action(ctx, inputs, outputs, config_file_path):
|
def _compile_action(ctx, inputs, outputs, config_file_path):
|
||||||
externs_files = []
|
summaries = depset()
|
||||||
non_externs_files = []
|
for dep in ctx.attr.deps:
|
||||||
for output in outputs:
|
if hasattr(dep, "collect_summaries_aspect_result"):
|
||||||
if output.basename.endswith(".es5.MF"):
|
summaries += dep.collect_summaries_aspect_result
|
||||||
ctx.file_action(output, content="")
|
|
||||||
else:
|
|
||||||
non_externs_files.append(output)
|
|
||||||
|
|
||||||
# TODO(alexeagle): For now we mock creation of externs files
|
action_inputs = inputs + summaries.to_list() + ctx.files.assets
|
||||||
for externs_file in externs_files:
|
# print("ASSETS", [a.path for a in ctx.files.assets])
|
||||||
ctx.file_action(output=externs_file, content="")
|
# print("INPUTS", ctx.label, [o.path for o in summaries if o.path.find("core/src") > 0])
|
||||||
|
|
||||||
action_inputs = inputs
|
|
||||||
if hasattr(ctx.attr, "node_modules"):
|
if hasattr(ctx.attr, "node_modules"):
|
||||||
action_inputs += [f for f in ctx.files.node_modules
|
action_inputs += [f for f in ctx.files.node_modules
|
||||||
if f.path.endswith(".ts") or f.path.endswith(".json")]
|
if f.path.endswith(".ts") or f.path.endswith(".json")]
|
||||||
if ctx.file.tsconfig:
|
if hasattr(ctx.attr, "tsconfig") and ctx.file.tsconfig:
|
||||||
action_inputs += [ctx.file.tsconfig]
|
action_inputs += [ctx.file.tsconfig]
|
||||||
|
|
||||||
# One at-sign makes this a params-file, enabling the worker strategy.
|
# One at-sign makes this a params-file, enabling the worker strategy.
|
||||||
# Two at-signs escapes the argument so it's passed through to ngc
|
# Two at-signs escapes the argument so it's passed through to ngc
|
||||||
# rather than the contents getting expanded.
|
# rather than the contents getting expanded.
|
||||||
if ctx.attr.supports_workers:
|
if ctx.attr._supports_workers:
|
||||||
arguments = ["@@" + config_file_path]
|
arguments = ["@@" + config_file_path]
|
||||||
else:
|
else:
|
||||||
arguments = ["-p", config_file_path]
|
arguments = ["-p", config_file_path]
|
||||||
|
@ -77,79 +118,75 @@ def _compile_action(ctx, inputs, outputs, config_file_path):
|
||||||
progress_message = "Compiling Angular templates (ngc) %s" % ctx.label,
|
progress_message = "Compiling Angular templates (ngc) %s" % ctx.label,
|
||||||
mnemonic = "AngularTemplateCompile",
|
mnemonic = "AngularTemplateCompile",
|
||||||
inputs = action_inputs,
|
inputs = action_inputs,
|
||||||
outputs = non_externs_files,
|
outputs = outputs,
|
||||||
arguments = arguments,
|
arguments = arguments,
|
||||||
executable = ctx.executable.compiler,
|
executable = ctx.executable.compiler,
|
||||||
execution_requirements = {
|
execution_requirements = {
|
||||||
"supports-workers": str(int(ctx.attr.supports_workers)),
|
"supports-workers": str(int(ctx.attr._supports_workers)),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _prodmode_compile_action(ctx, inputs, outputs, config_file_path):
|
||||||
|
outs = _expected_outs(ctx, ctx.label)
|
||||||
|
_compile_action(ctx, inputs, outputs + outs.closure_js, config_file_path)
|
||||||
|
|
||||||
def _devmode_compile_action(ctx, inputs, outputs, config_file_path):
|
def _devmode_compile_action(ctx, inputs, outputs, config_file_path):
|
||||||
# TODO(alexeagle): compile for feeding to Closure Compiler
|
outs = _expected_outs(ctx, ctx.label)
|
||||||
_compile_action(ctx, inputs, outputs + _expected_outs(ctx), config_file_path)
|
_compile_action(ctx, inputs, outputs + outs.devmode_js + outs.declarations + outs.summaries, config_file_path)
|
||||||
|
|
||||||
def _compile_ng(ctx):
|
def ng_module_impl(ctx, ts_compile_actions):
|
||||||
declarations = []
|
providers = ts_compile_actions(
|
||||||
for dep in ctx.attr.deps:
|
ctx, is_library=True, compile_action=_prodmode_compile_action,
|
||||||
if hasattr(dep, "typescript"):
|
devmode_compile_action=_devmode_compile_action,
|
||||||
declarations += dep.typescript.transitive_declarations
|
tsc_wrapped_tsconfig=_ngc_tsconfig,
|
||||||
|
outputs = _expected_outs)
|
||||||
|
|
||||||
tsconfig_json = ctx.new_file(ctx.label.name + "_tsconfig.json")
|
#addl_declarations = [_expected_outs(ctx)]
|
||||||
ctx.file_action(output=tsconfig_json, content=json_marshal(
|
#providers["typescript"]["declarations"] += addl_declarations
|
||||||
_ngc_tsconfig(ctx, ctx.files.srcs + declarations, ctx.files.srcs)))
|
#providers["typescript"]["transitive_declarations"] += addl_declarations
|
||||||
|
providers["angular"] = {
|
||||||
_devmode_compile_action(ctx, ctx.files.srcs + declarations + [tsconfig_json], [], tsconfig_json.path)
|
"summaries": _expected_outs(ctx, ctx.label).summaries
|
||||||
|
|
||||||
return {
|
|
||||||
"files": depset(_expected_outs(ctx)),
|
|
||||||
"typescript": {
|
|
||||||
# FIXME: expose the right outputs so this looks like a ts_library
|
|
||||||
"declarations": [],
|
|
||||||
"transitive_declarations": [],
|
|
||||||
"type_blacklisted_declarations": [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return providers
|
||||||
|
|
||||||
def _ng_module_impl(ctx):
|
def _ng_module_impl(ctx):
|
||||||
if ctx.attr.write_ng_outputs_only:
|
return ts_providers_dict_to_struct(ng_module_impl(ctx, compile_ts))
|
||||||
ts_providers = _compile_ng(ctx)
|
|
||||||
else:
|
|
||||||
ts_providers = compile_ts(ctx, is_library=True,
|
|
||||||
compile_action=_compile_action,
|
|
||||||
devmode_compile_action=_devmode_compile_action,
|
|
||||||
tsc_wrapped_tsconfig=_ngc_tsconfig)
|
|
||||||
|
|
||||||
addl_declarations = [o for o in _expected_outs(ctx) if o.path.endswith(".d.ts")]
|
NG_MODULE_ATTRIBUTES = {
|
||||||
ts_providers["typescript"]["declarations"] += addl_declarations
|
"srcs": attr.label_list(allow_files = [".ts"]),
|
||||||
ts_providers["typescript"]["transitive_declarations"] += addl_declarations
|
|
||||||
|
|
||||||
return ts_providers_dict_to_struct(ts_providers)
|
"deps": attr.label_list(aspects = DEPS_ASPECTS + [_collect_summaries_aspect]),
|
||||||
|
|
||||||
|
"assets": attr.label_list(allow_files = [
|
||||||
|
".css",
|
||||||
|
# TODO(alexeagle): change this to ".ng.html" when usages updated
|
||||||
|
".html",
|
||||||
|
]),
|
||||||
|
|
||||||
|
# TODO(alexeagle): wire up when we have i18n in bazel
|
||||||
|
"no_i18n": attr.bool(default = False),
|
||||||
|
|
||||||
|
"compiler": attr.label(
|
||||||
|
default = Label("//src/ngc-wrapped"),
|
||||||
|
executable = True,
|
||||||
|
cfg = "host",
|
||||||
|
),
|
||||||
|
|
||||||
|
# TODO(alexeagle): enable workers for ngc
|
||||||
|
"_supports_workers": attr.bool(default = False),
|
||||||
|
}
|
||||||
|
|
||||||
ng_module = rule(
|
ng_module = rule(
|
||||||
implementation = _ng_module_impl,
|
implementation = _ng_module_impl,
|
||||||
attrs = dict(COMMON_ATTRIBUTES, **{
|
attrs = COMMON_ATTRIBUTES + NG_MODULE_ATTRIBUTES + {
|
||||||
"srcs": attr.label_list(allow_files = True),
|
|
||||||
|
|
||||||
# To be used only to bootstrap @angular/core compilation,
|
|
||||||
# since we want to compile @angular/core with ngc, but ngc depends on
|
|
||||||
# @angular/core typescript output.
|
|
||||||
"write_ng_outputs_only": attr.bool(default = False),
|
|
||||||
"tsconfig": attr.label(allow_files = True, single_file = True),
|
"tsconfig": attr.label(allow_files = True, single_file = True),
|
||||||
"no_i18n": attr.bool(default = False),
|
|
||||||
# TODO(alexeagle): enable workers for ngc
|
|
||||||
"supports_workers": attr.bool(default = False),
|
|
||||||
"compiler": attr.label(
|
|
||||||
default = Label("//internal/ngc"),
|
|
||||||
executable = True,
|
|
||||||
cfg = "host",
|
|
||||||
),
|
|
||||||
# @// is special syntax for the "main" repository
|
# @// is special syntax for the "main" repository
|
||||||
# The default assumes the user specified a target "node_modules" in their
|
# The default assumes the user specified a target "node_modules" in their
|
||||||
# root BUILD file.
|
# root BUILD file.
|
||||||
"node_modules": attr.label(
|
"node_modules": attr.label(
|
||||||
default = Label("@//:node_modules")
|
default = Label("@//:node_modules")
|
||||||
),
|
),
|
||||||
}),
|
},
|
||||||
)
|
)
|
|
@ -6,9 +6,14 @@ ts_library(
|
||||||
name = "ngc_lib",
|
name = "ngc_lib",
|
||||||
srcs = ["index.ts"],
|
srcs = ["index.ts"],
|
||||||
deps = [
|
deps = [
|
||||||
|
# BEGIN-INTERNAL
|
||||||
|
# Only needed when compiling within the Angular repo.
|
||||||
|
# Users will get this dependency from node_modules.
|
||||||
"//packages/compiler-cli",
|
"//packages/compiler-cli",
|
||||||
|
# END-INTERNAL
|
||||||
"@build_bazel_rules_typescript//internal/tsc_wrapped"
|
"@build_bazel_rules_typescript//internal/tsc_wrapped"
|
||||||
],
|
],
|
||||||
|
tsconfig = ":tsconfig.json",
|
||||||
)
|
)
|
||||||
|
|
||||||
nodejs_binary(
|
nodejs_binary(
|
||||||
|
|
|
@ -5,28 +5,185 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
// TODO(chuckj): Remove the requirment for a fake 'reflect` implementation from
|
||||||
// TODO(chuckj): Remove the requirement for a fake 'reflect` implementation from
|
|
||||||
// the compiler
|
// the compiler
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata'; // from //third_party/javascript/node_modules/reflect_decorators:ts
|
||||||
|
|
||||||
import {calcProjectFileAndBasePath, createNgCompilerOptions, formatDiagnostics, performCompilation} from '@angular/compiler-cli';
|
import * as ng from '@angular/compiler-cli';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
// Note, the tsc_wrapped module comes from rules_typescript, not from @angular/tsc-wrapped
|
// Note, the tsc_wrapped module comes from rules_typescript, not from npm
|
||||||
import {parseTsconfig} from 'tsc_wrapped';
|
import {CompilerHost, UncachedFileLoader, parseTsconfig} from 'tsc_wrapped';
|
||||||
|
import * as tsickle from 'tsickle';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
function main(args: string[]) {
|
const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
||||||
|
// FIXME: we should be able to add the assets to the tsconfig so FileLoader
|
||||||
|
// knows about them
|
||||||
|
const NGC_NON_TS_INPUTS =
|
||||||
|
/(\.(ngsummary|ngstyle|ngfactory)(\.d)?\.ts|\.ngsummary\.json|\.css|\.html)$/;
|
||||||
|
// FIXME should need only summary, css, html
|
||||||
|
|
||||||
|
function topologicalSort(
|
||||||
|
result: tsickle.FileMap<boolean>, current: string, modulesManifest: tsickle.ModulesManifest,
|
||||||
|
visiting: tsickle.FileMap<boolean>) {
|
||||||
|
const referencedModules = modulesManifest.getReferencedModules(current);
|
||||||
|
if (!referencedModules) return; // not in the local set of sources.
|
||||||
|
for (const referencedModule of referencedModules) {
|
||||||
|
const referencedFileName = modulesManifest.getFileNameFromModule(referencedModule);
|
||||||
|
if (!referencedFileName) continue; // Ambient modules.
|
||||||
|
if (!result[referencedFileName]) {
|
||||||
|
if (visiting[referencedFileName]) {
|
||||||
|
const path = current + ' -> ' + Object.keys(visiting).join(' -> ');
|
||||||
|
throw new Error('Cyclical dependency between files:\n' + path);
|
||||||
|
}
|
||||||
|
visiting[referencedFileName] = true;
|
||||||
|
topologicalSort(result, referencedFileName, modulesManifest, visiting);
|
||||||
|
delete visiting[referencedFileName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[current] = true;
|
||||||
|
}
|
||||||
|
// TODO(alexeagle): move to tsc-wrapped in third_party so it's shared
|
||||||
|
export function constructManifest(
|
||||||
|
modulesManifest: tsickle.ModulesManifest,
|
||||||
|
host: {flattenOutDir: (f: string) => string}): string {
|
||||||
|
const result: tsickle.FileMap<boolean> = {};
|
||||||
|
for (const file of modulesManifest.fileNames) {
|
||||||
|
topologicalSort(result, file, modulesManifest, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: The object literal maintains insertion order.
|
||||||
|
return Object.keys(result).map(fn => host.flattenOutDir(fn)).join('\n') + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function main(args) {
|
||||||
const project = args[1];
|
const project = args[1];
|
||||||
const [{options: tsOptions, bazelOpts, files, config}] = parseTsconfig(project);
|
const [{options: tsOptions, bazelOpts, files, config}] = parseTsconfig(project);
|
||||||
const {basePath} = calcProjectFileAndBasePath(project);
|
|
||||||
const ngOptions = createNgCompilerOptions(basePath, config, tsOptions);
|
|
||||||
|
|
||||||
const {diagnostics} = performCompilation({rootNames: files, options: ngOptions});
|
const {basePath} = ng.calcProjectFileAndBasePath(project);
|
||||||
if (diagnostics.length) {
|
const ngOptions = ng.createNgCompilerOptions(basePath, config, tsOptions);
|
||||||
console.error(formatDiagnostics(ngOptions, diagnostics));
|
if (!bazelOpts.es5Mode) {
|
||||||
|
ngOptions.annotateForClosureCompiler = true;
|
||||||
|
ngOptions.annotationsAs = 'static fields';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function relativeToRootDir(filePath: string): string {
|
||||||
|
if (tsOptions.rootDir) {
|
||||||
|
const rel = path.relative(tsOptions.rootDir, filePath);
|
||||||
|
if (rel.indexOf('.') != 0) return rel;
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
const expectedOuts = [...config['angularCompilerOptions']['expectedOut']];
|
||||||
|
const tsHost = ts.createCompilerHost(tsOptions, true);
|
||||||
|
|
||||||
|
const originalWriteFile = tsHost.writeFile.bind(tsHost);
|
||||||
|
tsHost.writeFile =
|
||||||
|
(fileName: string, content: string, writeByteOrderMark: boolean,
|
||||||
|
onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => {
|
||||||
|
const relative = relativeToRootDir(fileName);
|
||||||
|
const expectedIdx = expectedOuts.findIndex(o => o === relative);
|
||||||
|
if (expectedIdx >= 0) {
|
||||||
|
expectedOuts.splice(expectedIdx, 1);
|
||||||
|
originalWriteFile(fileName, content, writeByteOrderMark, onError, sourceFiles);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Patch fileExists when resolving modules, so that ngc can ask TypeScript to
|
||||||
|
// resolve non-existing generated files that don't exist on disk, but are
|
||||||
|
// synthetic and added to the `programWithStubs` based on real inputs.
|
||||||
|
const generatedFileModuleResolverHost = Object.create(tsHost);
|
||||||
|
generatedFileModuleResolverHost.fileExists = (fileName: string) => {
|
||||||
|
const match = /^(.*?)\.(ngfactory|ngsummary|ngstyle|shim\.ngstyle)(.*)$/.exec(fileName);
|
||||||
|
if (match) {
|
||||||
|
const [, file, suffix, ext] = match;
|
||||||
|
// Performance: skip looking for files other than .d.ts or .ts
|
||||||
|
if (ext !== '.ts' && ext !== '.d.ts') return false;
|
||||||
|
if (suffix.indexOf('ngstyle') >= 0) {
|
||||||
|
// Look for foo.css on disk
|
||||||
|
fileName = file;
|
||||||
|
} else {
|
||||||
|
// Look for foo.d.ts or foo.ts on disk
|
||||||
|
fileName = file + (ext || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tsHost.fileExists(fileName);
|
||||||
|
};
|
||||||
|
|
||||||
|
function generatedFileModuleResolver(
|
||||||
|
moduleName: string, containingFile: string,
|
||||||
|
compilerOptions: ts.CompilerOptions): ts.ResolvedModuleWithFailedLookupLocations {
|
||||||
|
return ts.resolveModuleName(
|
||||||
|
moduleName, containingFile, compilerOptions, generatedFileModuleResolverHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bazelHost = new CompilerHost(
|
||||||
|
files, tsOptions, bazelOpts, tsHost, new UncachedFileLoader(), generatedFileModuleResolver);
|
||||||
|
bazelHost.allowNonHermeticRead = (filePath: string) =>
|
||||||
|
NGC_NON_TS_INPUTS.test(filePath) || filePath.split(path.sep).indexOf('node_modules') != -1;
|
||||||
|
bazelHost.shouldSkipTsickleProcessing = (fileName: string): boolean =>
|
||||||
|
bazelOpts.compilationTargetSrc.indexOf(fileName) === -1 && !NGC_NON_TS_INPUTS.test(fileName);
|
||||||
|
|
||||||
|
const ngHost = ng.createCompilerHost({options: ngOptions, tsHost: bazelHost});
|
||||||
|
|
||||||
|
ngHost.fileNameToModuleName = (importedFilePath: string, containingFilePath: string) =>
|
||||||
|
relativeToRootDir(importedFilePath).replace(EXT, '');
|
||||||
|
ngHost.toSummaryFileName = (fileName: string, referringSrcFileName: string) =>
|
||||||
|
ngHost.fileNameToModuleName(fileName, referringSrcFileName);
|
||||||
|
|
||||||
|
const tsickleOpts = {
|
||||||
|
googmodule: bazelOpts.googmodule,
|
||||||
|
es5Mode: bazelOpts.es5Mode,
|
||||||
|
prelude: bazelOpts.prelude,
|
||||||
|
untyped: bazelOpts.untyped,
|
||||||
|
typeBlackListPaths: new Set(bazelOpts.typeBlackListPaths),
|
||||||
|
transformDecorators: bazelOpts.tsickle,
|
||||||
|
transformTypesToClosure: bazelOpts.tsickle,
|
||||||
|
};
|
||||||
|
const emitCallback: ng.TsEmitCallback = ({
|
||||||
|
program,
|
||||||
|
targetSourceFile,
|
||||||
|
writeFile,
|
||||||
|
cancellationToken,
|
||||||
|
emitOnlyDtsFiles,
|
||||||
|
customTransformers = {},
|
||||||
|
}) =>
|
||||||
|
tsickle.emitWithTsickle(
|
||||||
|
program, bazelHost, tsickleOpts, bazelHost, ngOptions, targetSourceFile, writeFile,
|
||||||
|
cancellationToken, emitOnlyDtsFiles, {
|
||||||
|
beforeTs: customTransformers.before,
|
||||||
|
afterTs: customTransformers.after,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {diagnostics, emitResult} =
|
||||||
|
ng.performCompilation({rootNames: files, options: ngOptions, host: ngHost, emitCallback});
|
||||||
|
const tsickleEmitResult = emitResult as tsickle.EmitResult;
|
||||||
|
let externs = '/** @externs */\n';
|
||||||
|
if (diagnostics.length) {
|
||||||
|
console.error(ng.formatDiagnostics(ngOptions, diagnostics));
|
||||||
|
} else {
|
||||||
|
if (bazelOpts.tsickleGenerateExterns) {
|
||||||
|
externs += tsickle.getGeneratedExterns(tsickleEmitResult.externs);
|
||||||
|
}
|
||||||
|
if (bazelOpts.manifest) {
|
||||||
|
const manifest = constructManifest(tsickleEmitResult.modulesManifest, bazelHost);
|
||||||
|
fs.writeFileSync(bazelOpts.manifest, manifest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bazelOpts.tsickleExternsPath) {
|
||||||
|
// Note: when tsickleExternsPath is provided, we always write a file as a
|
||||||
|
// marker that compilation succeeded, even if it's empty (just containing an
|
||||||
|
// @externs).
|
||||||
|
fs.writeFileSync(bazelOpts.tsickleExternsPath, externs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const missing of expectedOuts) {
|
||||||
|
originalWriteFile(missing, '', false);
|
||||||
|
}
|
||||||
|
|
||||||
return diagnostics.some(d => d.category === ts.DiagnosticCategory.Error) ? 1 : 0;
|
return diagnostics.some(d => d.category === ts.DiagnosticCategory.Error) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["es5", "es2015.collection", "es2015.core"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Allows different paths for these imports in google3
|
||||||
|
load("@build_bazel_rules_typescript//internal:build_defs.bzl", "tsc_wrapped_tsconfig")
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@build_bazel_rules_typescript//internal:common/compilation.bzl",
|
||||||
|
"COMMON_ATTRIBUTES", "compile_ts", "DEPS_ASPECTS", "ts_providers_dict_to_struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@build_bazel_rules_typescript//internal:common/json_marshal.bzl", "json_marshal")
|
|
@ -91,11 +91,6 @@ export interface CompilerOptions extends ts.CompilerOptions {
|
||||||
// position.
|
// position.
|
||||||
disableExpressionLowering?: boolean;
|
disableExpressionLowering?: boolean;
|
||||||
|
|
||||||
// The list of expected files, when provided:
|
|
||||||
// - extra files are filtered out,
|
|
||||||
// - missing files are created empty.
|
|
||||||
expectedOut?: string[];
|
|
||||||
|
|
||||||
// Locale of the application
|
// Locale of the application
|
||||||
i18nOutLocale?: string;
|
i18nOutLocale?: string;
|
||||||
// Export format (xlf, xlf2 or xmb)
|
// Export format (xlf, xlf2 or xmb)
|
||||||
|
|
|
@ -143,22 +143,13 @@ class AngularCompilerProgram implements Program {
|
||||||
}): ts.EmitResult {
|
}): ts.EmitResult {
|
||||||
const emitMap = new Map<string, string>();
|
const emitMap = new Map<string, string>();
|
||||||
|
|
||||||
const expectedOut = this.options.expectedOut ?
|
|
||||||
this.options.expectedOut.map(f => path.resolve(process.cwd(), f)) :
|
|
||||||
undefined;
|
|
||||||
|
|
||||||
// Ensure that expected output files exist.
|
|
||||||
for (const out of expectedOut || []) {
|
|
||||||
this.host.writeFile(out, '', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emitResult = emitCallback({
|
const emitResult = emitCallback({
|
||||||
program: this.programWithStubs,
|
program: this.programWithStubs,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
options: this.options,
|
options: this.options,
|
||||||
targetSourceFile: undefined,
|
targetSourceFile: undefined,
|
||||||
writeFile:
|
writeFile: createWriteFileCallback(
|
||||||
createWriteFileCallback(emitFlags, this.host, this.metadataCache, emitMap, expectedOut),
|
emitFlags, this.host, this.metadataCache, emitMap, this.generatedFiles),
|
||||||
cancellationToken,
|
cancellationToken,
|
||||||
emitOnlyDtsFiles: (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS,
|
emitOnlyDtsFiles: (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS,
|
||||||
customTransformers: this.calculateTransforms(customTransformers)
|
customTransformers: this.calculateTransforms(customTransformers)
|
||||||
|
@ -399,7 +390,9 @@ function writeMetadata(
|
||||||
|
|
||||||
function createWriteFileCallback(
|
function createWriteFileCallback(
|
||||||
emitFlags: EmitFlags, host: ts.CompilerHost, metadataCache: LowerMetadataCache,
|
emitFlags: EmitFlags, host: ts.CompilerHost, metadataCache: LowerMetadataCache,
|
||||||
emitMap: Map<string, string>, expectedOut?: string[]) {
|
emitMap: Map<string, string>, generatedFiles: GeneratedFile[]) {
|
||||||
|
const genFileToSrcFile = new Map<string, string>();
|
||||||
|
generatedFiles.forEach(f => genFileToSrcFile.set(f.genFileUrl, f.srcFileUrl));
|
||||||
return (fileName: string, data: string, writeByteOrderMark: boolean,
|
return (fileName: string, data: string, writeByteOrderMark: boolean,
|
||||||
onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => {
|
onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => {
|
||||||
|
|
||||||
|
@ -407,14 +400,15 @@ function createWriteFileCallback(
|
||||||
|
|
||||||
if (sourceFiles && sourceFiles.length == 1) {
|
if (sourceFiles && sourceFiles.length == 1) {
|
||||||
srcFile = sourceFiles[0];
|
srcFile = sourceFiles[0];
|
||||||
emitMap.set(srcFile.fileName, fileName);
|
const originalSrcFile = genFileToSrcFile.get(srcFile.fileName) || srcFile.fileName;
|
||||||
|
emitMap.set(originalSrcFile, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const absFile = path.resolve(process.cwd(), fileName);
|
const absFile = path.resolve(process.cwd(), fileName);
|
||||||
const generatedFile = GENERATED_FILES.test(fileName);
|
const generatedFile = GENERATED_FILES.test(fileName);
|
||||||
|
|
||||||
// Don't emit unexpected files nor empty generated files
|
// Don't emit empty generated files
|
||||||
if ((!expectedOut || expectedOut.indexOf(absFile) > -1) && (!generatedFile || data)) {
|
if (!generatedFile || data) {
|
||||||
host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||||
|
|
||||||
if (srcFile && !generatedFile && (emitFlags & EmitFlags.Metadata) != 0) {
|
if (srcFile && !generatedFile && (emitFlags & EmitFlags.Metadata) != 0) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ if [[ ${TRAVIS} && (${CI_MODE} == "aio" || ${CI_MODE} == "aio_e2e" || ${CI_MODE}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Install bazel
|
# Install bazel
|
||||||
if [[ ${TRAVIS} && ${CI_MODE} == "bazel" ]]; then
|
if [[ ${TRAVIS} && (${CI_MODE} == "bazel" || ${CI_MODE} == "e2e_2") ]]; then
|
||||||
travisFoldStart "bazel-install"
|
travisFoldStart "bazel-install"
|
||||||
(
|
(
|
||||||
mkdir tmp
|
mkdir tmp
|
||||||
|
|
Loading…
Reference in New Issue