From 82ad2570844db913a82268160ed96a2995f5701f Mon Sep 17 00:00:00 2001 From: Bor Kae Hwang Date: Tue, 7 Jan 2020 01:11:04 -0700 Subject: [PATCH] Phase Scalafmt --- .scalafmt.conf | 15 +++ BUILD | 0 WORKSPACE | 29 +++++ scala/private/phases/phase_scalafmt.bzl | 81 ++++++++++++++ scala/private/phases/phases.bzl | 4 + scala/scalafmt/BUILD | 36 +++++++ scala/scalafmt/phase_scalafmt_ext.bzl | 54 ++++++++++ .../scalafmt/private/format-test.template.sh | 18 ++++ scala/scalafmt/private/format.template.sh | 33 ++++++ scala/scalafmt/scalafmt.bzl | 100 ++++++++++++++++++ scala/scalafmt/scalafmt/ScalafmtRunner.scala | 59 +++++++++++ test/scalafmt/BUILD | 47 ++++++++ test/scalafmt/formatted-test.scala | 8 ++ test/scalafmt/formatted.scala | 15 +++ test/scalafmt/phase_scalafmt_test.bzl | 16 +++ test/scalafmt/unformatted-test.scala | 8 ++ test/scalafmt/unformatted-test.template.scala | 8 ++ test/scalafmt/unformatted.scala | 18 ++++ test/scalafmt/unformatted.template.scala | 18 ++++ test/shell/test_scalafmt.sh | 58 ++++++++++ test_rules_scala.sh | 1 + 21 files changed, 626 insertions(+) create mode 100644 .scalafmt.conf create mode 100644 BUILD create mode 100644 scala/private/phases/phase_scalafmt.bzl create mode 100644 scala/scalafmt/BUILD create mode 100644 scala/scalafmt/phase_scalafmt_ext.bzl create mode 100644 scala/scalafmt/private/format-test.template.sh create mode 100644 scala/scalafmt/private/format.template.sh create mode 100644 scala/scalafmt/scalafmt.bzl create mode 100644 scala/scalafmt/scalafmt/ScalafmtRunner.scala create mode 100644 test/scalafmt/BUILD create mode 100644 test/scalafmt/formatted-test.scala create mode 100644 test/scalafmt/formatted.scala create mode 100644 test/scalafmt/phase_scalafmt_test.bzl create mode 100644 test/scalafmt/unformatted-test.scala create mode 100644 test/scalafmt/unformatted-test.template.scala create mode 100644 test/scalafmt/unformatted.scala create mode 100644 test/scalafmt/unformatted.template.scala create mode 100755 test/shell/test_scalafmt.sh diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000000..5490b5f714 --- /dev/null +++ b/.scalafmt.conf @@ -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 diff --git a/BUILD b/BUILD new file mode 100644 index 0000000000..e69de29bb2 diff --git a/WORKSPACE b/WORKSPACE index 44227568fa..3d48aa3b93 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -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 = [ diff --git a/scala/private/phases/phase_scalafmt.bzl b/scala/private/phases/phase_scalafmt.bzl new file mode 100644 index 0000000000..3eafd72bca --- /dev/null +++ b/scala/private/phases/phase_scalafmt.bzl @@ -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 = {}, + ) diff --git a/scala/private/phases/phases.bzl b/scala/private/phases/phases.bzl index c1b4e4b9ac..78323ef98d 100644 --- a/scala/private/phases/phases.bzl +++ b/scala/private/phases/phases.bzl @@ -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 @@ -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 diff --git a/scala/scalafmt/BUILD b/scala/scalafmt/BUILD new file mode 100644 index 0000000000..8fb46a0b47 --- /dev/null +++ b/scala/scalafmt/BUILD @@ -0,0 +1,36 @@ +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 = [ + "//src/java/io/bazel/rulesscala/worker", + "//external:io_bazel_rules_scala/scalafmt/geirsson_metaconfig_core", + "//external:io_bazel_rules_scala/scalafmt/argparse4j", + "//external:io_bazel_rules_scala/scalafmt/scalafmt_parsers", + "@scalafmt//:org_scalameta_scalafmt_core_2_11", + ], +) + +load( + "//scala/scalafmt:phase_scalafmt_ext.bzl", "scalafmt_singleton", +) + +scalafmt_singleton( + name = "phase_scalafmt", + visibility = ["//visibility:public"], +) diff --git a/scala/scalafmt/phase_scalafmt_ext.bzl b/scala/scalafmt/phase_scalafmt_ext.bzl new file mode 100644 index 0000000000..010684b74d --- /dev/null +++ b/scala/scalafmt/phase_scalafmt_ext.bzl @@ -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, +) diff --git a/scala/scalafmt/private/format-test.template.sh b/scala/scalafmt/private/format-test.template.sh new file mode 100644 index 0000000000..377f251d0a --- /dev/null +++ b/scala/scalafmt/private/format-test.template.sh @@ -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 diff --git a/scala/scalafmt/private/format.template.sh b/scala/scalafmt/private/format.template.sh new file mode 100644 index 0000000000..f481487737 --- /dev/null +++ b/scala/scalafmt/private/format.template.sh @@ -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 diff --git a/scala/scalafmt/scalafmt.bzl b/scala/scalafmt/scalafmt.bzl new file mode 100644 index 0000000000..0f32990139 --- /dev/null +++ b/scala/scalafmt/scalafmt.bzl @@ -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", + ) diff --git a/scala/scalafmt/scalafmt/ScalafmtRunner.scala b/scala/scalafmt/scalafmt/ScalafmtRunner.scala new file mode 100644 index 0000000000..42ed48998d --- /dev/null +++ b/scala/scalafmt/scalafmt/ScalafmtRunner.scala @@ -0,0 +1,59 @@ +package io.bazel.rules_scala.scalafmt + +import io.bazel.rulesscala.worker.{GenericWorker, Processor}; +import java.io.File +import java.nio.file.Files +import net.sourceforge.argparse4j.ArgumentParsers +import net.sourceforge.argparse4j.impl.Arguments +import org.scalafmt.Scalafmt +import org.scalafmt.config.Config +import org.scalafmt.util.FileOps +import scala.annotation.tailrec +import scala.io.Codec + +object ScalafmtRunner extends GenericWorker(new ScalafmtProcessor) { + def main(args: Array[String]) { + try run(args) + catch { + case x: Exception => + x.printStackTrace() + System.exit(1) + } + } +} + +class ScalafmtProcessor extends Processor { + def processRequest(args: java.util.List[String]) { + var argsArrayBuffer = scala.collection.mutable.ArrayBuffer[String]() + for (i <- 0 to args.size-1) { + argsArrayBuffer += args.get(i) + } + val parser = ArgumentParsers.newFor("scalafmt").addHelp(true).defaultFormatWidth(80).fromFilePrefix("@").build + parser.addArgument("--config").required(true).`type`(Arguments.fileType) + parser.addArgument("input").`type`(Arguments.fileType) + parser.addArgument("output").`type`(Arguments.fileType) + + val namespace = parser.parseArgsOrFail(argsArrayBuffer.toArray) + + val source = FileOps.readFile(namespace.get[File]("input"))(Codec.UTF8) + + val config = Config.fromHoconFile(namespace.get[File]("config")).get + @tailrec + def format(code: String): String = { + val formatted = Scalafmt.format(code, config).get + if (code == formatted) code else format(formatted) + } + + val output = try { + format(source) + } catch { + case e @ (_: org.scalafmt.Error | _: scala.meta.parsers.ParseException) => { + System.out.println("Unable to format file due to bug in scalafmt") + System.out.println(e.toString) + source + } + } + + Files.write(namespace.get[File]("output").toPath, output.getBytes) + } +} diff --git a/test/scalafmt/BUILD b/test/scalafmt/BUILD new file mode 100644 index 0000000000..6389040db0 --- /dev/null +++ b/test/scalafmt/BUILD @@ -0,0 +1,47 @@ +load( + "//test/scalafmt:phase_scalafmt_test.bzl", + "scalafmt_scala_binary", + "scalafmt_scala_library", + "scalafmt_scala_test" +) + +### scala_binary ### +scalafmt_scala_binary( + name = "formatted-binary", + srcs = ["formatted.scala"], + format = True, + main_class = "scalarules.test.scalafmt.Format", +) + +scalafmt_scala_binary( + name = "unformatted-binary", + srcs = ["unformatted.scala"], + format = True, + main_class = "scalarules.test.scalafmt.Format", +) + +### scala_library ### +scalafmt_scala_library( + name = "formatted-library", + srcs = ["formatted.scala"], + format = True, +) + +scalafmt_scala_library( + name = "unformatted-library", + srcs = ["unformatted.scala"], + format = True, +) + +### scala_test ### +scalafmt_scala_test( + name = "formatted-test", + srcs = ["formatted-test.scala"], + format = True, +) + +scalafmt_scala_test( + name = "unformatted-test", + srcs = ["unformatted-test.scala"], + format = True, +) diff --git a/test/scalafmt/formatted-test.scala b/test/scalafmt/formatted-test.scala new file mode 100644 index 0000000000..cee6fd8715 --- /dev/null +++ b/test/scalafmt/formatted-test.scala @@ -0,0 +1,8 @@ +package scalarules.test.scalafmt +import org.scalatest._ +class FormatTest extends FlatSpec { + val message = "We will format this test!" + "FormatTest" should "be formatted" in { + assert(message.equals("We will format this test!")) + } +} diff --git a/test/scalafmt/formatted.scala b/test/scalafmt/formatted.scala new file mode 100644 index 0000000000..0b6baf5f32 --- /dev/null +++ b/test/scalafmt/formatted.scala @@ -0,0 +1,15 @@ +package scalarules.test.scalafmt +object Format { + def main(args: Array[String]) { + val greeting: String = + "Hello, world!" + val warning1 = "Be careful with this test" + val warning2 = "小心這個測試" + val warning3 = "このテストに注意してください" + val warning4 = "이 시험에 조심하십시오" + val warning5 = "كن حذرا مع هذا الاختبار" + val warning6 = "Hãy cẩn thận với bài kiểm tra này" + val warning7 = "Будьте осторожны с этим тестом" + val warning8 = "😁✊🚀🍟💯" + } +} diff --git a/test/scalafmt/phase_scalafmt_test.bzl b/test/scalafmt/phase_scalafmt_test.bzl new file mode 100644 index 0000000000..ed5e46602a --- /dev/null +++ b/test/scalafmt/phase_scalafmt_test.bzl @@ -0,0 +1,16 @@ +load( + "//scala:advanced_usage/scala.bzl", + "make_scala_binary", + "make_scala_library", + "make_scala_test", +) +load( + "//scala/scalafmt:phase_scalafmt_ext.bzl", + "ext_scalafmt", +) + +scalafmt_scala_binary = make_scala_binary(ext_scalafmt) + +scalafmt_scala_library = make_scala_library(ext_scalafmt) + +scalafmt_scala_test = make_scala_test(ext_scalafmt) diff --git a/test/scalafmt/unformatted-test.scala b/test/scalafmt/unformatted-test.scala new file mode 100644 index 0000000000..c14e2f220e --- /dev/null +++ b/test/scalafmt/unformatted-test.scala @@ -0,0 +1,8 @@ + package scalarules.test.scalafmt + import org.scalatest._ + class FormatTest extends FlatSpec { + val message = "We will format this test!" + "FormatTest" should "be formatted" in { + assert ( message.equals( "We will format this test!" ) ) + } +} diff --git a/test/scalafmt/unformatted-test.template.scala b/test/scalafmt/unformatted-test.template.scala new file mode 100644 index 0000000000..c14e2f220e --- /dev/null +++ b/test/scalafmt/unformatted-test.template.scala @@ -0,0 +1,8 @@ + package scalarules.test.scalafmt + import org.scalatest._ + class FormatTest extends FlatSpec { + val message = "We will format this test!" + "FormatTest" should "be formatted" in { + assert ( message.equals( "We will format this test!" ) ) + } +} diff --git a/test/scalafmt/unformatted.scala b/test/scalafmt/unformatted.scala new file mode 100644 index 0000000000..aae8276141 --- /dev/null +++ b/test/scalafmt/unformatted.scala @@ -0,0 +1,18 @@ + package scalarules.test.scalafmt + object Format { + def main ( args: + + + Array [String ]) { + val greeting: String = + "Hello, world!" + val warning1 = "Be careful with this test" + val warning2 = "小心這個測試" + val warning3 = "このテストに注意してください" + val warning4 = "이 시험에 조심하십시오" + val warning5 = "كن حذرا مع هذا الاختبار" + val warning6 = "Hãy cẩn thận với bài kiểm tra này" + val warning7 = "Будьте осторожны с этим тестом" + val warning8 = "😁✊🚀🍟💯" + } +} diff --git a/test/scalafmt/unformatted.template.scala b/test/scalafmt/unformatted.template.scala new file mode 100644 index 0000000000..aae8276141 --- /dev/null +++ b/test/scalafmt/unformatted.template.scala @@ -0,0 +1,18 @@ + package scalarules.test.scalafmt + object Format { + def main ( args: + + + Array [String ]) { + val greeting: String = + "Hello, world!" + val warning1 = "Be careful with this test" + val warning2 = "小心這個測試" + val warning3 = "このテストに注意してください" + val warning4 = "이 시험에 조심하십시오" + val warning5 = "كن حذرا مع هذا الاختبار" + val warning6 = "Hãy cẩn thận với bài kiểm tra này" + val warning7 = "Будьте осторожны с этим тестом" + val warning8 = "😁✊🚀🍟💯" + } +} diff --git a/test/shell/test_scalafmt.sh b/test/shell/test_scalafmt.sh new file mode 100755 index 0000000000..8fd4bd80e5 --- /dev/null +++ b/test/shell/test_scalafmt.sh @@ -0,0 +1,58 @@ +# shellcheck source=./test_runner.sh +dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +. "${dir}"/test_runner.sh +. "${dir}"/test_helper.sh +runner=$(get_test_runner "${1:-local}") + +run_non_default_formatting() { + set +e + + FILE_PATH="$( dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) )"/scalafmt + RULE_TYPE=$1 + FILENAME="formatted" + if [[ $RULE_TYPE = test ]]; then + FILENAME="formatted-test" + fi + + bazel run //test/scalafmt:formatted-$RULE_TYPE.format-test + if [ $? -ne 0 ]; then + echo -e "${RED} formatted-$RULE_TYPE.format-test should be a formatted target. $NC" + exit 1 + fi + + bazel run //test/scalafmt:unformatted-$RULE_TYPE.format-test + if [ $? -eq 0 ]; then + echo -e "${RED} unformatted-$RULE_TYPE.format-test should be an unformatted target. $NC" + exit 1 + fi + + bazel run //test/scalafmt:unformatted-$RULE_TYPE.format + if [ $? -ne 0 ]; then + echo -e "${RED} unformatted-$RULE_TYPE.format should run formatting. $NC" + exit 1 + fi + + diff $FILE_PATH/un${FILENAME}.scala $FILE_PATH/${FILENAME}.scala + if [ $? -ne 0 ]; then + echo -e "${RED} un${FILENAME}.scala should be the same as ${FILENAME}.scala after formatting. $NC" + exit 1 + fi + + cp $FILE_PATH/un${FILENAME}.template.scala $FILE_PATH/un${FILENAME}.scala +} + +test_scalafmt_binary() { + run_non_default_formatting binary +} + +test_scalafmt_library() { + run_non_default_formatting library +} + +test_scalafmt_test() { + run_non_default_formatting test +} + +$runner test_scalafmt_binary +$runner test_scalafmt_library +$runner test_scalafmt_test diff --git a/test_rules_scala.sh b/test_rules_scala.sh index e8456fabfe..c57f626610 100755 --- a/test_rules_scala.sh +++ b/test_rules_scala.sh @@ -30,6 +30,7 @@ $runner bazel test //test/... --extra_toolchains="//test_expect_failure/plus_one . "${test_dir}"/test_junit.sh . "${test_dir}"/test_misc.sh . "${test_dir}"/test_phase.sh +. "${test_dir}"/test_scalafmt.sh . "${test_dir}"/test_scala_binary.sh . "${test_dir}"/test_scalac_jvm_flags.sh . "${test_dir}"/test_scala_classpath.sh