Skip to content

Commit

Permalink
feat: support --noEmit for type-checking as a validation action
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobgardner authored and jbedard committed Sep 5, 2024
1 parent ed84211 commit 652e569
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 55 deletions.
12 changes: 7 additions & 5 deletions docs/rules.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions e2e/test/common.bats
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function tsconfig() {
local target="ES2020"
local module_resolution="node"
local composite="false"
local no_emit="false"
local trace_resolution="false"
local extended_diagnostics="false"
while (($# > 0)); do
Expand Down Expand Up @@ -111,6 +112,10 @@ function tsconfig() {
composite="true"
shift
;;
--no-emit)
shift
no_emit="true"
;;
--target)
shift
target="$1"
Expand Down Expand Up @@ -139,6 +144,7 @@ function tsconfig() {
"isolatedModules": $isolated_modules,
"sourceMap": $source_map,
"declaration": $declaration,
"noEmit": $no_emit,
"target": "$target",
"moduleResolution": "$module_resolution",
"traceResolution": $trace_resolution,
Expand All @@ -161,6 +167,9 @@ function ts_project() {
local source_map=""
local declaration=""
local composite=""
local transpiler=""
local mock_transpiler_disabled="#"
local no_emit=""
while (($# > 0)); do
case "$1" in
--path)
Expand Down Expand Up @@ -215,6 +224,15 @@ function ts_project() {
shift
composite="composite = True,"
;;
--transpiler-mock)
shift;
transpiler="transpiler = mock,"
mock_transpiler_disabled=""
;;
--no-emit)
shift
no_emit="no_emit = True,"
;;
--)
shift
break
Expand All @@ -238,6 +256,7 @@ function ts_project() {
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
${npm_link_all_packages}load("@npm//:defs.bzl", "npm_link_all_packages")
${npm_link_all_packages}npm_link_all_packages(name = "node_modules")
${mock_transpiler_disabled}load("@aspect_rules_ts//ts/test:mock_transpiler.bzl", "mock")
ts_project(
name = "${name}",
Expand All @@ -250,6 +269,8 @@ ts_project(
$source_map
$declaration
$composite
$transpiler
$no_emit
)
EOF
}
Expand Down
38 changes: 38 additions & 0 deletions e2e/test/validation.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
load "common.bats"

setup() {
cd $BATS_FILE_TMPDIR
}

teardown() {
bazel shutdown
rm -rf $BATS_FILE_TMPDIR/*
}


@test 'When tsc is only used for type-checking with a type-error, should pass when validations are disabled' {
workspace

echo "export const a: string = 1;" > ./source.ts
tsconfig --declaration
ts_project --transpiler-mock --declaration --src "source.ts"

run bazel build :foo --norun_validations
assert_success
run cat bazel-bin/source.js
assert_success
# Mock transpiler just copies source input to output
assert_output -p 'export const a: string = 1;'
}

@test 'When tsc is only used for type-checking with a type-error, should fail when validations are enabled' {
workspace

echo "export const a: string = 1;" > ./source.ts
tsconfig --no-emit
ts_project --no-emit --src "source.ts"

run bazel build :foo --run_validations
assert_failure
assert_output -p "error TS2322: Type 'number' is not assignable to type 'string'"
}
16 changes: 16 additions & 0 deletions examples/no_emit/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
load("@bazel_skylib//rules:write_file.bzl", "write_file")

write_file(
name = "gen_ts",
out = "a.ts",
content = [
"export const a: number = 42",
],
)

ts_project(
name = "no-emit",
srcs = ["a.ts"],
no_emit = True,
)
7 changes: 7 additions & 0 deletions examples/no_emit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
// Workaround https://github.com/microsoft/TypeScript/issues/59036
"exclude": [],
"compilerOptions": {
"noEmit": true
}
}
13 changes: 13 additions & 0 deletions examples/transpiler/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,16 @@ ts_project(
source_map = True,
transpiler = babel,
)

# Transpiler with no dts being omitted
ts_project(
name = "no-emit",
srcs = ["big.ts"],
no_emit = True,
transpiler = babel,
tsconfig = {
"compilerOptions": {
"noEmit": True,
},
},
)
15 changes: 10 additions & 5 deletions ts/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def ts_project(
preserve_jsx = False,
composite = False,
incremental = False,
no_emit = False,
emit_declaration_only = False,
transpiler = None,
ts_build_info_file = None,
Expand Down Expand Up @@ -215,6 +216,8 @@ def ts_project(
Instructs Bazel to expect a `.tsbuildinfo` output and a `.d.ts` output for each `.ts` source.
incremental: Whether the `incremental` bit is set in the tsconfig.
Instructs Bazel to expect a `.tsbuildinfo` output.
no_emit: Whether the `noEmit` bit is set in the tsconfig.
Instructs Bazel *not* to expect any outputs. Only a validation action is used.
emit_declaration_only: Whether the `emitDeclarationOnly` bit is set in the tsconfig.
Instructs Bazel *not* to expect `.js` or `.js.map` outputs for `.ts` sources.
ts_build_info_file: The user-specified value of `tsBuildInfoFile` from the tsconfig.
Expand Down Expand Up @@ -276,6 +279,7 @@ def ts_project(
source_map = compiler_options.setdefault("sourceMap", source_map)
declaration = compiler_options.setdefault("declaration", declaration)
declaration_map = compiler_options.setdefault("declarationMap", declaration_map)
no_emit = compiler_options.setdefault("noEmit", no_emit)
emit_declaration_only = compiler_options.setdefault("emitDeclarationOnly", emit_declaration_only)
allow_js = compiler_options.setdefault("allowJs", allow_js)
if resolve_json_module != None:
Expand Down Expand Up @@ -309,14 +313,14 @@ def ts_project(
typings_out_dir = declaration_dir if declaration_dir else out_dir
tsbuildinfo_path = ts_build_info_file if ts_build_info_file else name + ".tsbuildinfo"

tsc_typings_outs = _lib.calculate_typings_outs(srcs, typings_out_dir, root_dir, declaration, composite, allow_js)
tsc_typing_maps_outs = _lib.calculate_typing_maps_outs(srcs, typings_out_dir, root_dir, declaration_map, allow_js)
tsc_typings_outs = _lib.calculate_typings_outs(srcs, typings_out_dir, root_dir, declaration, composite, allow_js, no_emit)
tsc_typing_maps_outs = _lib.calculate_typing_maps_outs(srcs, typings_out_dir, root_dir, declaration_map, allow_js, no_emit)

tsc_js_outs = []
tsc_map_outs = []
if not transpiler or transpiler == "tsc":
tsc_js_outs = _lib.calculate_js_outs(srcs, out_dir, root_dir, allow_js, resolve_json_module, preserve_jsx, emit_declaration_only)
tsc_map_outs = _lib.calculate_map_outs(srcs, out_dir, root_dir, source_map, preserve_jsx, emit_declaration_only)
if no_emit or not transpiler or transpiler == "tsc":
tsc_js_outs = _lib.calculate_js_outs(srcs, out_dir, root_dir, allow_js, resolve_json_module, preserve_jsx, no_emit, emit_declaration_only)
tsc_map_outs = _lib.calculate_map_outs(srcs, out_dir, root_dir, source_map, preserve_jsx, no_emit, emit_declaration_only)
tsc_target_name = name
else:
# To stitch together a tree of ts_project where transpiler is a separate rule,
Expand Down Expand Up @@ -401,6 +405,7 @@ def ts_project(
typings_outs = tsc_typings_outs,
typing_maps_outs = tsc_typing_maps_outs,
buildinfo_out = tsbuildinfo_path if composite or incremental else None,
no_emit = no_emit,
emit_declaration_only = emit_declaration_only,
tsc = tsc,
tsc_worker = tsc_worker,
Expand Down
19 changes: 11 additions & 8 deletions ts/private/ts_lib.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ COMPILER_OPTION_ATTRS = {
"declaration_map": attr.bool(
doc = "https://www.typescriptlang.org/tsconfig#declarationMap",
),
"no_emit": attr.bool(
doc = "https://www.typescriptlang.org/tsconfig#noEmit",
),
"emit_declaration_only": attr.bool(
doc = "https://www.typescriptlang.org/tsconfig#emitDeclarationOnly",
),
Expand Down Expand Up @@ -234,8 +237,8 @@ def _validate_tsconfig_dirs(root_dir, out_dir, typings_out_dir):
if typings_out_dir and typings_out_dir.find("../") != -1:
fail("typings_out_dir cannot output to parent directory")

def _calculate_js_outs(srcs, out_dir, root_dir, allow_js, resolve_json_module, preserve_jsx, emit_declaration_only):
if emit_declaration_only:
def _calculate_js_outs(srcs, out_dir, root_dir, allow_js, resolve_json_module, preserve_jsx, no_emit, emit_declaration_only):
if no_emit or emit_declaration_only:
return []

exts = {
Expand All @@ -253,8 +256,8 @@ def _calculate_js_outs(srcs, out_dir, root_dir, allow_js, resolve_json_module, p

return _to_js_out_paths(srcs, out_dir, root_dir, allow_js, resolve_json_module, exts)

def _calculate_map_outs(srcs, out_dir, root_dir, source_map, preserve_jsx, emit_declaration_only):
if not source_map or emit_declaration_only:
def _calculate_map_outs(srcs, out_dir, root_dir, source_map, preserve_jsx, no_emit, emit_declaration_only):
if no_emit or not source_map or emit_declaration_only:
return []

exts = {
Expand All @@ -269,8 +272,8 @@ def _calculate_map_outs(srcs, out_dir, root_dir, source_map, preserve_jsx, emit_

return _to_js_out_paths(srcs, out_dir, root_dir, False, False, exts)

def _calculate_typings_outs(srcs, typings_out_dir, root_dir, declaration, composite, allow_js):
if not (declaration or composite):
def _calculate_typings_outs(srcs, typings_out_dir, root_dir, declaration, composite, allow_js, no_emit):
if no_emit or not (declaration or composite):
return []

exts = {
Expand All @@ -283,8 +286,8 @@ def _calculate_typings_outs(srcs, typings_out_dir, root_dir, declaration, compos

return _to_js_out_paths(srcs, typings_out_dir, root_dir, allow_js, False, exts)

def _calculate_typing_maps_outs(srcs, typings_out_dir, root_dir, declaration_map, allow_js):
if not declaration_map:
def _calculate_typing_maps_outs(srcs, typings_out_dir, root_dir, declaration_map, allow_js, no_emit):
if no_emit or not declaration_map:
return []

exts = {
Expand Down
Loading

0 comments on commit 652e569

Please sign in to comment.