Skip to content

Commit 82ad257

Browse files
committed
Phase Scalafmt
1 parent bd0c388 commit 82ad257

21 files changed

+626
-0
lines changed

.scalafmt.conf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
align.openParenCallSite = false
2+
align.openParenDefnSite = false
3+
continuationIndent.defnSite = 2
4+
danglingParentheses = true
5+
docstrings = JavaDoc
6+
importSelectors = singleLine
7+
maxColumn = 120
8+
newlines.afterImplicitKWInVerticalMultiline = true
9+
rewrite.redundantBraces.stringInterpolation = true
10+
rewrite.rules = [
11+
RedundantParens,
12+
PreferCurlyFors,
13+
SortImports
14+
]
15+
unindentTopLevelOperators = false

BUILD

Whitespace-only changes.

WORKSPACE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,35 @@ load("//specs2:specs2_junit.bzl", "specs2_junit_repositories")
4040

4141
specs2_junit_repositories()
4242

43+
load("//scala/scalafmt:scalafmt.bzl", "scalafmt_default_config", "scalafmt_repositories")
44+
45+
scalafmt_repositories()
46+
47+
scalafmt_default_config()
48+
49+
RULES_JVM_EXTERNAL_TAG = "3.1"
50+
51+
http_archive(
52+
name = "rules_jvm_external",
53+
sha256 = "e246373de2353f3d34d35814947aa8b7d0dd1a58c2f7a6c41cfeaff3007c2d14",
54+
strip_prefix = "rules_jvm_external-{}".format(RULES_JVM_EXTERNAL_TAG),
55+
type = "zip",
56+
url = "https://github.com/bazelbuild/rules_jvm_external/archive/{}.zip".format(RULES_JVM_EXTERNAL_TAG),
57+
)
58+
59+
load("@rules_jvm_external//:defs.bzl", "maven_install")
60+
61+
maven_install(
62+
name = "scalafmt",
63+
artifacts = [
64+
"org.scalameta:scalafmt-core_2.11:2.0.0",
65+
],
66+
fetch_sources = True,
67+
repositories = [
68+
"http://central.maven.org/maven2",
69+
],
70+
)
71+
4372
load("//scala:scala_cross_version.bzl", "default_scala_major_version", "scala_mvn_artifact")
4473

4574
MAVEN_SERVER_URLS = [
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#
2+
# PHASE: phase scalafmt
3+
#
4+
# Outputs to format the scala files when it is explicitly specified
5+
#
6+
def phase_scalafmt(ctx, p):
7+
if ctx.attr.format:
8+
manifest, files = _build_format(ctx)
9+
_format_runner(ctx, manifest, files)
10+
_format_tester(ctx, manifest, files)
11+
else:
12+
ctx.actions.write(
13+
output = ctx.outputs.scalafmt_runner,
14+
content = "",
15+
is_executable = True,
16+
)
17+
ctx.actions.write(
18+
output = ctx.outputs.scalafmt_testrunner,
19+
content = "",
20+
is_executable = True,
21+
)
22+
23+
def _build_format(ctx):
24+
files = []
25+
runner_inputs, _, runner_manifests = ctx.resolve_command(tools = [ctx.attr._fmt])
26+
manifest_content = []
27+
for src in ctx.files.srcs:
28+
if src.path.endswith(".scala") and src.is_source:
29+
file = ctx.actions.declare_file(src.short_path)
30+
files.append(file)
31+
args = ctx.actions.args()
32+
args.add("--config")
33+
args.add(ctx.file.config.path)
34+
args.add(src.path)
35+
args.add(file.path)
36+
args.set_param_file_format("multiline")
37+
args.use_param_file("@%s", use_always = True)
38+
ctx.actions.run(
39+
arguments = ["--jvm_flag=-Dfile.encoding=UTF-8", args],
40+
executable = ctx.executable._fmt,
41+
outputs = [file],
42+
input_manifests = runner_manifests,
43+
inputs = [ctx.file.config, src],
44+
tools = runner_inputs,
45+
execution_requirements = {"supports-workers": "1"},
46+
mnemonic = "ScalaFmt",
47+
)
48+
manifest_content.append("{} {}".format(src.short_path, file.short_path))
49+
50+
manifest = ctx.actions.declare_file("format/{}/manifest.txt".format(ctx.label.name))
51+
ctx.actions.write(manifest, "\n".join(manifest_content) + "\n")
52+
53+
return manifest, files
54+
55+
def _format_runner(ctx, manifest, files):
56+
ctx.actions.run_shell(
57+
inputs = [ctx.file._runner, manifest] + files,
58+
outputs = [ctx.outputs.scalafmt_runner],
59+
command = "cat $1 | sed -e s#%workspace%#$2# -e s#%manifest%#$3# > $4",
60+
arguments = [
61+
ctx.file._runner.path,
62+
ctx.workspace_name,
63+
manifest.short_path,
64+
ctx.outputs.scalafmt_runner.path,
65+
],
66+
execution_requirements = {},
67+
)
68+
69+
def _format_tester(ctx, manifest, files):
70+
ctx.actions.run_shell(
71+
inputs = [ctx.file._testrunner, manifest] + files,
72+
outputs = [ctx.outputs.scalafmt_testrunner],
73+
command = "cat $1 | sed -e s#%workspace%#$2# -e s#%manifest%#$3# > $4",
74+
arguments = [
75+
ctx.file._testrunner.path,
76+
ctx.workspace_name,
77+
manifest.short_path,
78+
ctx.outputs.scalafmt_testrunner.path,
79+
],
80+
execution_requirements = {},
81+
)

scala/private/phases/phases.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ load("@io_bazel_rules_scala//scala/private:phases/phase_declare_executable.bzl",
6565
load("@io_bazel_rules_scala//scala/private:phases/phase_merge_jars.bzl", _phase_merge_jars = "phase_merge_jars")
6666
load("@io_bazel_rules_scala//scala/private:phases/phase_jvm_flags.bzl", _phase_jvm_flags = "phase_jvm_flags")
6767
load("@io_bazel_rules_scala//scala/private:phases/phase_coverage_runfiles.bzl", _phase_coverage_runfiles = "phase_coverage_runfiles")
68+
load("@io_bazel_rules_scala//scala/private:phases/phase_scalafmt.bzl", _phase_scalafmt = "phase_scalafmt")
6869

6970
# API
7071
run_phases = _run_phases
@@ -134,6 +135,9 @@ phase_library_runfiles = _phase_library_runfiles
134135
phase_scalatest_runfiles = _phase_scalatest_runfiles
135136
phase_common_runfiles = _phase_common_runfiles
136137

138+
# scalafmt
139+
phase_scalafmt = _phase_scalafmt
140+
137141
# final
138142
phase_binary_final = _phase_binary_final
139143
phase_library_final = _phase_library_final

scala/scalafmt/BUILD

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
load("//scala:scala.bzl", "scala_binary")
2+
3+
filegroup(
4+
name = "runner",
5+
srcs = ["private/format.template.sh"],
6+
visibility = ["//visibility:public"],
7+
)
8+
9+
filegroup(
10+
name = "testrunner",
11+
srcs = ["private/format-test.template.sh"],
12+
visibility = ["//visibility:public"],
13+
)
14+
15+
scala_binary(
16+
name = "scalafmt",
17+
srcs = glob(["scalafmt/ScalafmtRunner.scala"]),
18+
main_class = "io.bazel.rules_scala.scalafmt.ScalafmtRunner",
19+
visibility = ["//visibility:public"],
20+
deps = [
21+
"//src/java/io/bazel/rulesscala/worker",
22+
"//external:io_bazel_rules_scala/scalafmt/geirsson_metaconfig_core",
23+
"//external:io_bazel_rules_scala/scalafmt/argparse4j",
24+
"//external:io_bazel_rules_scala/scalafmt/scalafmt_parsers",
25+
"@scalafmt//:org_scalameta_scalafmt_core_2_11",
26+
],
27+
)
28+
29+
load(
30+
"//scala/scalafmt:phase_scalafmt_ext.bzl", "scalafmt_singleton",
31+
)
32+
33+
scalafmt_singleton(
34+
name = "phase_scalafmt",
35+
visibility = ["//visibility:public"],
36+
)

scala/scalafmt/phase_scalafmt_ext.bzl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
load(
2+
"//scala:advanced_usage/providers.bzl",
3+
_ScalaRulePhase = "ScalaRulePhase",
4+
)
5+
load(
6+
"//scala/private:phases/phases.bzl",
7+
_phase_scalafmt = "phase_scalafmt",
8+
)
9+
10+
ext_scalafmt = {
11+
"attrs": {
12+
"config": attr.label(
13+
allow_single_file = [".conf"],
14+
default = "@scalafmt_default//:config",
15+
doc = "The Scalafmt configuration file.",
16+
),
17+
"_fmt": attr.label(
18+
cfg = "host",
19+
default = "//scala/scalafmt",
20+
executable = True,
21+
),
22+
"_runner": attr.label(
23+
allow_single_file = True,
24+
default = "//scala/scalafmt:runner",
25+
),
26+
"_testrunner": attr.label(
27+
allow_single_file = True,
28+
default = "//scala/scalafmt:testrunner",
29+
),
30+
"format": attr.bool(
31+
default = False,
32+
),
33+
},
34+
"outputs": {
35+
"scalafmt_runner": "%{name}.format",
36+
"scalafmt_testrunner": "%{name}.format-test",
37+
},
38+
"phase_providers": [
39+
"//scala/scalafmt:phase_scalafmt",
40+
],
41+
}
42+
43+
def _scalafmt_singleton_implementation(ctx):
44+
return [
45+
_ScalaRulePhase(
46+
custom_phases = [
47+
("$", "", "scalafmt", _phase_scalafmt),
48+
],
49+
),
50+
]
51+
52+
scalafmt_singleton = rule(
53+
implementation = _scalafmt_singleton_implementation,
54+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash -e
2+
RUNPATH="${TEST_SRCDIR-$0.runfiles}"/%workspace%
3+
WORKSPACE_ROOT="${1:-$BUILD_WORKSPACE_DIRECTORY}"
4+
NONDEFAULTPATH=(${RUNPATH//bin/ })
5+
NONDEFAULTPATH="${NONDEFAULTPATH[0]}"bin
6+
7+
EXIT=0
8+
while read original formatted; do
9+
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
10+
if ! cmp -s "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted"; then
11+
echo $original
12+
diff "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted" || true
13+
EXIT=1
14+
fi
15+
fi
16+
done < "$NONDEFAULTPATH"/%manifest%
17+
18+
exit $EXIT
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash -e
2+
RUNPATH="${TEST_SRCDIR-$0.runfiles}"/%workspace%
3+
WORKSPACE_ROOT="${1:-$BUILD_WORKSPACE_DIRECTORY}"
4+
5+
if [ -f "$RUNPATH"/%manifest% ]; then
6+
while read original formatted; do
7+
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
8+
if ! cmp -s "$RUNPATH/$original" "$RUNPATH/$formatted"; then
9+
if [ -z "$WORKSPACE_ROOT" ]; then
10+
echo "$original"
11+
diff "$RUNPATH/$original" "$RUNPATH/$formatted" || true
12+
EXIT=1
13+
else
14+
echo "Formatting $original"
15+
cp "$RUNPATH/$formatted" "$WORKSPACE_ROOT/$original"
16+
fi
17+
fi
18+
fi
19+
done < "$RUNPATH"/%manifest%
20+
else
21+
NONDEFAULTPATH=(${RUNPATH//bin/ })
22+
NONDEFAULTPATH="${NONDEFAULTPATH[0]}"bin
23+
while read original formatted; do
24+
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
25+
if ! cmp -s "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted"; then
26+
echo "Formatting $original"
27+
cp "$NONDEFAULTPATH/$formatted" "$WORKSPACE_ROOT/$original"
28+
fi
29+
fi
30+
done < "$NONDEFAULTPATH"/%manifest%
31+
fi
32+
33+
exit $EXIT

scala/scalafmt/scalafmt.bzl

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
load(
2+
"//scala:scala_cross_version.bzl",
3+
_default_scala_version = "default_scala_version",
4+
_extract_major_version = "extract_major_version",
5+
_scala_mvn_artifact = "scala_mvn_artifact",
6+
)
7+
load(
8+
"@io_bazel_rules_scala//scala:scala_maven_import_external.bzl",
9+
_scala_maven_import_external = "scala_maven_import_external",
10+
)
11+
12+
def scalafmt_default_config(path = ".scalafmt.conf"):
13+
build = []
14+
build.append("filegroup(")
15+
build.append(" name = \"config\",")
16+
build.append(" srcs = [\"{}\"],".format(path))
17+
build.append(" visibility = [\"//visibility:public\"],")
18+
build.append(")")
19+
native.new_local_repository(name = "scalafmt_default", build_file_content = "\n".join(build), path = "")
20+
21+
def scalafmt_repositories(
22+
scala_version = _default_scala_version(),
23+
maven_servers = ["http://central.maven.org/maven2"]):
24+
major_version = _extract_major_version(scala_version)
25+
26+
scala_jar_shas = {
27+
"2.11": {
28+
"scalafmt_parsers": "acde4faa648c61f1d76f7a1152116738c0b0b80ae2fab8ceae83c061c29aadf1",
29+
"metaconfig_core": "8abb4e48507486d0b323b440bb021bddd56366e502002025fdaf10025d2650c2",
30+
"scalafmt_core": "84bac5ed8c85e61851ef427f045b7bfd149d857cb543b41c85b8353fb8c47aff",
31+
},
32+
"2.12": {
33+
"scalafmt_parsers": "9dc726dab95870b193dee3ed4d11985fa38ca09640768a7c86d8f80c715c5567",
34+
"metaconfig_core": "495817d90ecb4c432ee0afa7e79b4d005e6a6f90a270e113e15fe7d2d5559dfd",
35+
"scalafmt_core": "02562f176a7d070230ef2da6192f2d15afd62ea173eaf8ca02a7afb89262d233",
36+
},
37+
}
38+
39+
scala_version_jar_shas = scala_jar_shas[major_version]
40+
41+
_scala_maven_import_external(
42+
name = "scalafmt_parsers",
43+
artifact = _scala_mvn_artifact(
44+
"org.scalameta:parsers:4.2.0",
45+
major_version,
46+
),
47+
artifact_sha256 = scala_version_jar_shas["scalafmt_parsers"],
48+
licenses = ["notice"],
49+
server_urls = maven_servers,
50+
)
51+
52+
native.bind(
53+
name = "io_bazel_rules_scala/scalafmt/scalafmt_parsers",
54+
actual = "@scalafmt_parsers",
55+
)
56+
57+
_scala_maven_import_external(
58+
name = "geirsson_metaconfig_core",
59+
artifact = _scala_mvn_artifact(
60+
"com.geirsson:metaconfig-core:0.8.3",
61+
major_version,
62+
),
63+
artifact_sha256 = scala_version_jar_shas["metaconfig_core"],
64+
licenses = ["notice"],
65+
server_urls = maven_servers,
66+
)
67+
68+
native.bind(
69+
name = "io_bazel_rules_scala/scalafmt/geirsson_metaconfig_core",
70+
actual = "@geirsson_metaconfig_core",
71+
)
72+
73+
_scala_maven_import_external(
74+
name = "scalafmt_core",
75+
artifact = _scala_mvn_artifact(
76+
"org.scalameta:scalafmt-core:2.0.0",
77+
major_version,
78+
),
79+
artifact_sha256 = scala_version_jar_shas["scalafmt_core"],
80+
licenses = ["notice"],
81+
server_urls = maven_servers,
82+
)
83+
84+
native.bind(
85+
name = "io_bazel_rules_scala/scalafmt/scalafmt_core",
86+
actual = "@scalafmt_core",
87+
)
88+
89+
_scala_maven_import_external(
90+
name = "argparse4j",
91+
artifact = "net.sourceforge.argparse4j:argparse4j:0.8.1",
92+
artifact_sha256 = "98cb5468cac609f3bc07856f2e34088f50dc114181237c48d20ca69c3265d044",
93+
licenses = ["notice"],
94+
server_urls = maven_servers,
95+
)
96+
97+
native.bind(
98+
name = "io_bazel_rules_scala/scalafmt/argparse4j",
99+
actual = "@argparse4j",
100+
)

0 commit comments

Comments
 (0)