Skip to content

Commit

Permalink
feat: add emitIsolatedDts support
Browse files Browse the repository at this point in the history
  • Loading branch information
jbedard committed Aug 27, 2024
1 parent 885a985 commit 002ac69
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 24 deletions.
6 changes: 4 additions & 2 deletions docs/swc.md

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

15 changes: 15 additions & 0 deletions e2e/emit_types/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Import Aspect bazelrc presets
try-import %workspace%/../../.aspect/bazelrc/bazel7.bazelrc
import %workspace%/../../.aspect/bazelrc/convenience.bazelrc
import %workspace%/../../.aspect/bazelrc/correctness.bazelrc
import %workspace%/../../.aspect/bazelrc/debug.bazelrc
import %workspace%/../../.aspect/bazelrc/javascript.bazelrc
import %workspace%/../../.aspect/bazelrc/performance.bazelrc

### YOUR PROJECT SPECIFIC OPTIONS GO HERE ###

# Load any settings & overrides specific to the current user from `.aspect/bazelrc/user.bazelrc`.
# This file should appear in `.gitignore` so that settings are not shared with team members. This
# should be last statement in this config so the user configuration is able to overwrite flags from
# this file. See https://bazel.build/configure/best-practices#bazelrc-file.
try-import %workspace%/../../.aspect/bazelrc/user.bazelrc
1 change: 1 addition & 0 deletions e2e/emit_types/.bazelversion
31 changes: 31 additions & 0 deletions e2e/emit_types/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
load("@aspect_rules_swc//swc:defs.bzl", "swc")
load("@bazel_skylib//rules:build_test.bzl", "build_test")

swc(
name = "compile",
srcs = [
"a.ts",
"b.ts",
],
)

swc(
name = "compile_emit_dts",
srcs = [
"a.ts",
"b.ts",
],
experimental_emit_isolated_dts = True,
)

build_test(
name = "test",
targets = [
":compile",
":compile_emit_dts",
"a.js",
"b.js",
"a.d.ts",
"b.d.ts",
],
)
14 changes: 14 additions & 0 deletions e2e/emit_types/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
bazel_dep(name = "aspect_rules_swc", version = "0.0.0", dev_dependency = True)
local_path_override(
module_name = "aspect_rules_swc",
path = "../..",
)

bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True)

# Optional: specify a custom swc toolchain instead of the default
swc = use_extension("@aspect_rules_swc//swc:extensions.bzl", "swc", dev_dependency = True)
swc.toolchain(
name = "swc",
swc_version = "v1.6.6",
)
31 changes: 31 additions & 0 deletions e2e/emit_types/WORKSPACE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Override http_archive for local testing
local_repository(
name = "aspect_rules_swc",
path = "../..",
)

#---SNIP--- Below here is re-used in the snippet published on releases

###################
# rules_swc setup #
###################

# Fetches the rules_swc dependencies.
# If you want to have a different version of some dependency,
# you should fetch it *before* calling this.
# Alternatively, you can skip calling this function, so long as you've
# already fetched all the dependencies.
load("@aspect_rules_swc//swc:dependencies.bzl", "rules_swc_dependencies")

rules_swc_dependencies()

# Fetches a SWC cli from
# https://github.com/swc-project/swc/releases
# If you'd rather compile it from source, you can use rules_rust, fetch the project,
# then register the toolchain yourself. (Note, this is not yet documented)
load("@aspect_rules_swc//swc:repositories.bzl", "swc_register_toolchains")

swc_register_toolchains(
name = "swc",
swc_version = "v1.6.6",
)
1 change: 1 addition & 0 deletions e2e/emit_types/WORKSPACE.bzlmod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This file replaces `WORKSPACE.bazel` when --enable_bzlmod is set.
1 change: 1 addition & 0 deletions e2e/emit_types/a.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const A = 1;
3 changes: 3 additions & 0 deletions e2e/emit_types/b.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { A } from "./a";

export const B: typeof A = 1;
9 changes: 7 additions & 2 deletions swc/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,22 @@ def swc(name, srcs, args = [], data = [], plugins = [], output_dir = False, swcr
# Determine js & map outputs
js_outs = []
map_outs = []
dts_outs = []

if not output_dir:
js_outs = _swc_lib.calculate_js_outs(srcs, out_dir, root_dir)
map_outs = _swc_lib.calculate_map_outs(srcs, source_maps, out_dir, root_dir)
if kwargs.get("experimental_emit_isolated_dts", False):
dts_outs = _swc_lib.calculate_dts_outs(srcs, out_dir, root_dir)
else:
js_outs = _swc_lib.calculate_js_outs(srcs, out_dir, root_dir)
map_outs = _swc_lib.calculate_map_outs(srcs, source_maps, out_dir, root_dir)

swc_compile(
name = name,
srcs = srcs,
plugins = plugins,
js_outs = js_outs,
map_outs = map_outs,
dts_outs = dts_outs,
output_dir = output_dir,
source_maps = source_maps,
args = args,
Expand Down
77 changes: 57 additions & 20 deletions swc/private/swc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ https://docs.aspect.build/rulesets/aspect_rules_js/docs/js_library#data for more
"root_dir": attr.string(
doc = "a subdirectory under the input package which should be consider the root directory of all the input files",
),
"experimental_emit_isolated_dts": attr.bool(
doc = "Emit .d.ts files for TypeScript sources",
default = False,
),
}

_outputs = {
Expand All @@ -75,6 +79,10 @@ There should be one for each entry in srcs."""),
"map_outs": attr.output_list(doc = """list of expected source map output files.
Can be empty, meaning no source maps should be produced.
If non-empty, there should be one for each entry in srcs."""),
"dts_outs": attr.output_list(doc = """list of expected TypeScript declaration files.
Can be empty, meaning no dts files should be produced.
If non-empty, there should be one for each entry in srcs."""),
}

Expand Down Expand Up @@ -183,6 +191,24 @@ def _calculate_map_outs(srcs, source_maps, out_dir, root_dir):
out.append(map_out)
return out

def _to_dts_out(src, out_dir, root_dir):
if not _is_supported_src(src):
return None
exts = {
"*": ".d.ts",
}
dts_out = src[:src.rindex(".")] + _replace_ext(src, exts)
dts_out = _to_out_path(dts_out, out_dir, root_dir)
return dts_out

def _calculate_dts_outs(srcs, out_dir, root_dir):
out = []
for f in srcs:
dts_out = _to_dts_out(f, out_dir, root_dir)
if dts_out:
out.append(dts_out)
return out

def _calculate_source_file(ctx, src):
if not (ctx.attr.out_dir or ctx.attr.root_dir):
return src.basename
Expand Down Expand Up @@ -217,6 +243,10 @@ def _swc_impl(ctx):
args = ctx.actions.args()
args.add("compile")

if ctx.attr.swcrc:
args.add("--config-file", ctx.file.swcrc)
inputs.append(ctx.file.swcrc)

# Add user specified arguments *before* rule supplied arguments
args.add_all(ctx.attr.args)

Expand Down Expand Up @@ -248,6 +278,15 @@ def _swc_impl(ctx):
inputs.extend(ctx.files.plugins)
args.add_all(plugin_args)

if ctx.attr.experimental_emit_isolated_dts:
args.add_all(["--config-json", json.encode({
"jsc": {
"experimental": {
"emitIsolatedDts": True,
},
},
})])

if ctx.attr.output_dir:
if len(ctx.attr.srcs) != 1:
fail("Under output_dir, there must be a single entry in srcs")
Expand All @@ -261,18 +300,12 @@ def _swc_impl(ctx):

args.add("--out-dir", output_dir.path)

src_args = ctx.actions.args()
if ctx.attr.swcrc:
src_args.add("--config-file", ctx.file.swcrc)
inputs.append(ctx.file.swcrc)

_swc_action(
ctx,
swc_toolchain.swcinfo.swc_binary,
inputs = inputs,
arguments = [
args,
src_args,
ctx.files.srcs[0].path,
],
outputs = output_sources,
Expand All @@ -296,28 +329,29 @@ def _swc_impl(ctx):
if not js_out_path:
# This source file is not a supported src
continue
js_out = ctx.actions.declare_file(js_out_path)
outputs = [js_out]
map_out_path = _to_map_out(src_path, ctx.attr.source_maps, ctx.attr.out_dir, ctx.attr.root_dir)

if map_out_path:
js_map_out = ctx.actions.declare_file(map_out_path)
outputs.append(js_map_out)

src_inputs = [src] + inputs
outputs = []

if ctx.attr.swcrc:
src_args.add("--config-file", ctx.file.swcrc)
src_inputs.append(ctx.file.swcrc)
if not ctx.attr.experimental_emit_isolated_dts:
js_out = ctx.actions.declare_file(js_out_path)
outputs.append(js_out)
map_out_path = _to_map_out(src_path, ctx.attr.source_maps, ctx.attr.out_dir, ctx.attr.root_dir)

src_args.add("--out-file", js_out)
if map_out_path:
js_map_out = ctx.actions.declare_file(map_out_path)
outputs.append(js_map_out)

output_sources.extend(outputs)
src_args.add("--out-file", js_out)
else:
dts_out_path = _to_dts_out(src_path, ctx.attr.out_dir, ctx.attr.root_dir)
dts_out = ctx.actions.declare_file(dts_out_path)
outputs.append(dts_out)
src_args.add("--out-file", dts_out)

_swc_action(
ctx,
swc_toolchain.swcinfo.swc_binary,
inputs = src_inputs,
inputs = [src] + inputs,
arguments = [
args,
src_args,
Expand All @@ -326,6 +360,8 @@ def _swc_impl(ctx):
outputs = outputs,
)

output_sources.extend(outputs)

output_sources_depset = depset(output_sources)

transitive_sources = js_lib_helpers.gather_transitive_sources(
Expand Down Expand Up @@ -377,4 +413,5 @@ swc = struct(
SUPPORTED_EXTENSIONS = _SUPPORTED_EXTENSIONS,
calculate_js_outs = _calculate_js_outs,
calculate_map_outs = _calculate_map_outs,
calculate_dts_outs = _calculate_dts_outs,
)

0 comments on commit 002ac69

Please sign in to comment.