Skip to content

Commit

Permalink
Phase Scalafmt
Browse files Browse the repository at this point in the history
  • Loading branch information
borkaehw committed Jan 8, 2020
1 parent bd0c388 commit d5cccec
Show file tree
Hide file tree
Showing 21 changed files with 627 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
align.openParenCallSite = false
align.openParenDefnSite = false
continuationIndent.defnSite = 2
danglingParentheses = true
docstrings = JavaDoc
importSelectors = singleLine
maxColumn = 120
newlines.afterImplicitKWInVerticalMultiline = true
rewrite.redundantBraces.stringInterpolation = true
rewrite.rules = [
RedundantParens,
PreferCurlyFors,
SortImports
]
unindentTopLevelOperators = false
Empty file added BUILD
Empty file.
29 changes: 29 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,35 @@ load("//specs2:specs2_junit.bzl", "specs2_junit_repositories")

specs2_junit_repositories()

load("//scala/scalafmt:scalafmt.bzl", "scalafmt_default_config", "scalafmt_repositories")

scalafmt_repositories()

scalafmt_default_config()

RULES_JVM_EXTERNAL_TAG = "3.1"

http_archive(
name = "rules_jvm_external",
sha256 = "e246373de2353f3d34d35814947aa8b7d0dd1a58c2f7a6c41cfeaff3007c2d14",
strip_prefix = "rules_jvm_external-{}".format(RULES_JVM_EXTERNAL_TAG),
type = "zip",
url = "https://github.com/bazelbuild/rules_jvm_external/archive/{}.zip".format(RULES_JVM_EXTERNAL_TAG),
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
name = "scalafmt",
artifacts = [
"org.scalameta:scalafmt-core_2.11:2.0.0",
],
fetch_sources = True,
repositories = [
"http://central.maven.org/maven2",
],
)

load("//scala:scala_cross_version.bzl", "default_scala_major_version", "scala_mvn_artifact")

MAVEN_SERVER_URLS = [
Expand Down
81 changes: 81 additions & 0 deletions scala/private/phases/phase_scalafmt.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#
# PHASE: phase scalafmt
#
# Outputs to format the scala files when it is explicitly specified
#
def phase_scalafmt(ctx, p):
if ctx.attr.format:
manifest, files = _build_format(ctx)
_format_runner(ctx, manifest, files)
_format_tester(ctx, manifest, files)
else:
ctx.actions.write(
output = ctx.outputs.scalafmt_runner,
content = "",
is_executable = True,
)
ctx.actions.write(
output = ctx.outputs.scalafmt_testrunner,
content = "",
is_executable = True,
)

def _build_format(ctx):
files = []
runner_inputs, _, runner_manifests = ctx.resolve_command(tools = [ctx.attr._fmt])
manifest_content = []
for src in ctx.files.srcs:
if src.path.endswith(".scala") and src.is_source:
file = ctx.actions.declare_file(src.short_path)
files.append(file)
args = ctx.actions.args()
args.add("--config")
args.add(ctx.file.config.path)
args.add(src.path)
args.add(file.path)
args.set_param_file_format("multiline")
args.use_param_file("@%s", use_always = True)
ctx.actions.run(
arguments = ["--jvm_flag=-Dfile.encoding=UTF-8", args],
executable = ctx.executable._fmt,
outputs = [file],
input_manifests = runner_manifests,
inputs = [ctx.file.config, src],
tools = runner_inputs,
execution_requirements = {"supports-workers": "1"},
mnemonic = "ScalaFmt",
)
manifest_content.append("{} {}".format(src.short_path, file.short_path))

manifest = ctx.actions.declare_file("format/{}/manifest.txt".format(ctx.label.name))
ctx.actions.write(manifest, "\n".join(manifest_content) + "\n")

return manifest, files

def _format_runner(ctx, manifest, files):
ctx.actions.run_shell(
inputs = [ctx.file._runner, manifest] + files,
outputs = [ctx.outputs.scalafmt_runner],
command = "cat $1 | sed -e s#%workspace%#$2# -e s#%manifest%#$3# > $4",
arguments = [
ctx.file._runner.path,
ctx.workspace_name,
manifest.short_path,
ctx.outputs.scalafmt_runner.path,
],
execution_requirements = {},
)

def _format_tester(ctx, manifest, files):
ctx.actions.run_shell(
inputs = [ctx.file._testrunner, manifest] + files,
outputs = [ctx.outputs.scalafmt_testrunner],
command = "cat $1 | sed -e s#%workspace%#$2# -e s#%manifest%#$3# > $4",
arguments = [
ctx.file._testrunner.path,
ctx.workspace_name,
manifest.short_path,
ctx.outputs.scalafmt_testrunner.path,
],
execution_requirements = {},
)
4 changes: 4 additions & 0 deletions scala/private/phases/phases.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ load("@io_bazel_rules_scala//scala/private:phases/phase_declare_executable.bzl",
load("@io_bazel_rules_scala//scala/private:phases/phase_merge_jars.bzl", _phase_merge_jars = "phase_merge_jars")
load("@io_bazel_rules_scala//scala/private:phases/phase_jvm_flags.bzl", _phase_jvm_flags = "phase_jvm_flags")
load("@io_bazel_rules_scala//scala/private:phases/phase_coverage_runfiles.bzl", _phase_coverage_runfiles = "phase_coverage_runfiles")
load("@io_bazel_rules_scala//scala/private:phases/phase_scalafmt.bzl", _phase_scalafmt = "phase_scalafmt")

# API
run_phases = _run_phases
Expand Down Expand Up @@ -134,6 +135,9 @@ phase_library_runfiles = _phase_library_runfiles
phase_scalatest_runfiles = _phase_scalatest_runfiles
phase_common_runfiles = _phase_common_runfiles

# scalafmt
phase_scalafmt = _phase_scalafmt

# final
phase_binary_final = _phase_binary_final
phase_library_final = _phase_library_final
Expand Down
37 changes: 37 additions & 0 deletions scala/scalafmt/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
load("//scala:scala.bzl", "scala_binary")

filegroup(
name = "runner",
srcs = ["private/format.template.sh"],
visibility = ["//visibility:public"],
)

filegroup(
name = "testrunner",
srcs = ["private/format-test.template.sh"],
visibility = ["//visibility:public"],
)

scala_binary(
name = "scalafmt",
srcs = glob(["scalafmt/ScalafmtRunner.scala"]),
main_class = "io.bazel.rules_scala.scalafmt.ScalafmtRunner",
visibility = ["//visibility:public"],
deps = [
"//external:io_bazel_rules_scala/scalafmt/argparse4j",
"//external:io_bazel_rules_scala/scalafmt/geirsson_metaconfig_core",
"//external:io_bazel_rules_scala/scalafmt/scalafmt_parsers",
"//src/java/io/bazel/rulesscala/worker",
"@scalafmt//:org_scalameta_scalafmt_core_2_11",
],
)

load(
"//scala/scalafmt:phase_scalafmt_ext.bzl",
"scalafmt_singleton",
)

scalafmt_singleton(
name = "phase_scalafmt",
visibility = ["//visibility:public"],
)
54 changes: 54 additions & 0 deletions scala/scalafmt/phase_scalafmt_ext.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
load(
"//scala:advanced_usage/providers.bzl",
_ScalaRulePhase = "ScalaRulePhase",
)
load(
"//scala/private:phases/phases.bzl",
_phase_scalafmt = "phase_scalafmt",
)

ext_scalafmt = {
"attrs": {
"config": attr.label(
allow_single_file = [".conf"],
default = "@scalafmt_default//:config",
doc = "The Scalafmt configuration file.",
),
"_fmt": attr.label(
cfg = "host",
default = "//scala/scalafmt",
executable = True,
),
"_runner": attr.label(
allow_single_file = True,
default = "//scala/scalafmt:runner",
),
"_testrunner": attr.label(
allow_single_file = True,
default = "//scala/scalafmt:testrunner",
),
"format": attr.bool(
default = False,
),
},
"outputs": {
"scalafmt_runner": "%{name}.format",
"scalafmt_testrunner": "%{name}.format-test",
},
"phase_providers": [
"//scala/scalafmt:phase_scalafmt",
],
}

def _scalafmt_singleton_implementation(ctx):
return [
_ScalaRulePhase(
custom_phases = [
("$", "", "scalafmt", _phase_scalafmt),
],
),
]

scalafmt_singleton = rule(
implementation = _scalafmt_singleton_implementation,
)
18 changes: 18 additions & 0 deletions scala/scalafmt/private/format-test.template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash -e
RUNPATH="${TEST_SRCDIR-$0.runfiles}"/%workspace%
WORKSPACE_ROOT="${1:-$BUILD_WORKSPACE_DIRECTORY}"
NONDEFAULTPATH=(${RUNPATH//bin/ })
NONDEFAULTPATH="${NONDEFAULTPATH[0]}"bin

EXIT=0
while read original formatted; do
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
if ! cmp -s "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted"; then
echo $original
diff "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted" || true
EXIT=1
fi
fi
done < "$NONDEFAULTPATH"/%manifest%

exit $EXIT
33 changes: 33 additions & 0 deletions scala/scalafmt/private/format.template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash -e
RUNPATH="${TEST_SRCDIR-$0.runfiles}"/%workspace%
WORKSPACE_ROOT="${1:-$BUILD_WORKSPACE_DIRECTORY}"

if [ -f "$RUNPATH"/%manifest% ]; then
while read original formatted; do
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
if ! cmp -s "$RUNPATH/$original" "$RUNPATH/$formatted"; then
if [ -z "$WORKSPACE_ROOT" ]; then
echo "$original"
diff "$RUNPATH/$original" "$RUNPATH/$formatted" || true
EXIT=1
else
echo "Formatting $original"
cp "$RUNPATH/$formatted" "$WORKSPACE_ROOT/$original"
fi
fi
fi
done < "$RUNPATH"/%manifest%
else
NONDEFAULTPATH=(${RUNPATH//bin/ })
NONDEFAULTPATH="${NONDEFAULTPATH[0]}"bin
while read original formatted; do
if [[ ! -z "$original" ]] && [[ ! -z "$formatted" ]]; then
if ! cmp -s "$WORKSPACE_ROOT/$original" "$NONDEFAULTPATH/$formatted"; then
echo "Formatting $original"
cp "$NONDEFAULTPATH/$formatted" "$WORKSPACE_ROOT/$original"
fi
fi
done < "$NONDEFAULTPATH"/%manifest%
fi

exit $EXIT
100 changes: 100 additions & 0 deletions scala/scalafmt/scalafmt.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
load(
"//scala:scala_cross_version.bzl",
_default_scala_version = "default_scala_version",
_extract_major_version = "extract_major_version",
_scala_mvn_artifact = "scala_mvn_artifact",
)
load(
"@io_bazel_rules_scala//scala:scala_maven_import_external.bzl",
_scala_maven_import_external = "scala_maven_import_external",
)

def scalafmt_default_config(path = ".scalafmt.conf"):
build = []
build.append("filegroup(")
build.append(" name = \"config\",")
build.append(" srcs = [\"{}\"],".format(path))
build.append(" visibility = [\"//visibility:public\"],")
build.append(")")
native.new_local_repository(name = "scalafmt_default", build_file_content = "\n".join(build), path = "")

def scalafmt_repositories(
scala_version = _default_scala_version(),
maven_servers = ["http://central.maven.org/maven2"]):
major_version = _extract_major_version(scala_version)

scala_jar_shas = {
"2.11": {
"scalafmt_parsers": "acde4faa648c61f1d76f7a1152116738c0b0b80ae2fab8ceae83c061c29aadf1",
"metaconfig_core": "8abb4e48507486d0b323b440bb021bddd56366e502002025fdaf10025d2650c2",
"scalafmt_core": "84bac5ed8c85e61851ef427f045b7bfd149d857cb543b41c85b8353fb8c47aff",
},
"2.12": {
"scalafmt_parsers": "9dc726dab95870b193dee3ed4d11985fa38ca09640768a7c86d8f80c715c5567",
"metaconfig_core": "495817d90ecb4c432ee0afa7e79b4d005e6a6f90a270e113e15fe7d2d5559dfd",
"scalafmt_core": "02562f176a7d070230ef2da6192f2d15afd62ea173eaf8ca02a7afb89262d233",
},
}

scala_version_jar_shas = scala_jar_shas[major_version]

_scala_maven_import_external(
name = "scalafmt_parsers",
artifact = _scala_mvn_artifact(
"org.scalameta:parsers:4.2.0",
major_version,
),
artifact_sha256 = scala_version_jar_shas["scalafmt_parsers"],
licenses = ["notice"],
server_urls = maven_servers,
)

native.bind(
name = "io_bazel_rules_scala/scalafmt/scalafmt_parsers",
actual = "@scalafmt_parsers",
)

_scala_maven_import_external(
name = "geirsson_metaconfig_core",
artifact = _scala_mvn_artifact(
"com.geirsson:metaconfig-core:0.8.3",
major_version,
),
artifact_sha256 = scala_version_jar_shas["metaconfig_core"],
licenses = ["notice"],
server_urls = maven_servers,
)

native.bind(
name = "io_bazel_rules_scala/scalafmt/geirsson_metaconfig_core",
actual = "@geirsson_metaconfig_core",
)

_scala_maven_import_external(
name = "scalafmt_core",
artifact = _scala_mvn_artifact(
"org.scalameta:scalafmt-core:2.0.0",
major_version,
),
artifact_sha256 = scala_version_jar_shas["scalafmt_core"],
licenses = ["notice"],
server_urls = maven_servers,
)

native.bind(
name = "io_bazel_rules_scala/scalafmt/scalafmt_core",
actual = "@scalafmt_core",
)

_scala_maven_import_external(
name = "argparse4j",
artifact = "net.sourceforge.argparse4j:argparse4j:0.8.1",
artifact_sha256 = "98cb5468cac609f3bc07856f2e34088f50dc114181237c48d20ca69c3265d044",
licenses = ["notice"],
server_urls = maven_servers,
)

native.bind(
name = "io_bazel_rules_scala/scalafmt/argparse4j",
actual = "@argparse4j",
)
Loading

0 comments on commit d5cccec

Please sign in to comment.