Skip to content

Commit

Permalink
Scalafmt, Scalafix, and tpolecat (#275)
Browse files Browse the repository at this point in the history
* Installed scalafix SBT plugin

* Installed tpolecat

* Installed scalafmt
  • Loading branch information
KarelCemus authored Feb 2, 2024
1 parent 1b9cdda commit 0042f4e
Show file tree
Hide file tree
Showing 106 changed files with 3,003 additions and 2,176 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ jobs:
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sbt --client "+clean; +compile; +Test/compile; +coverage; +test; +coverageReport; +coveralls;"
sbt --client "+clean; +compile; +Test/compile; lint; +coverage; +test; +coverageReport; +coveralls;"
19 changes: 19 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
rules = [
ExplicitResultTypes
LeakingImplicitClassVal
NoAutoTupling
NoValInForComprehension
OrganizeImports
ProcedureSyntax
RedundantSyntax
RemoveUnused
]

RemoveUnused {
imports = false // handled by OrganizeImports
}

OrganizeImports {
# Allign with IntelliJ IDEA so that they don't fight each other
groupedImports = Merge
}
168 changes: 168 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
version = "3.7.17"
runner.dialect = scala213
maxColumn = 300

// https://scalameta.org/scalafmt/docs/configuration.html#projectgit
project.git = true

fileOverride {
"glob:**/project/**.scala" {
runner.dialect = scala212
}
"glob:**/*.sbt" {
runner.dialect = sbt1
}
}

// ---------------------
// alignment
// ---------------------
align.preset = most
// align code behind -> e.g. in for ... yield
align.arrowEnumeratorGenerator = true
// multiline strings
align.stripMargin = true
assumeStandardLibraryStripMargin = true
// align also multiline statements
align.multiline = true
// don't break lines just because of alignment
align.allowOverflow = true
// align '='
align.tokens."+" = [
{
code = "="
owners = [{
parents = ["Template"]
}]
}
{
code = "="
owners = [{
regex = "Enumerator\\."
parents = ["Term\\.ForYield"]
}]
}
]
// align vals and types equally
align.treeCategory."Defn.Val" = "given/val/var/def"
align.treeCategory."Defn.Type" = "given/val/var/def"

// ---------------------
// indentation
// ---------------------
// identation of function calls
indent.callSite = 2
// indentation of "if" and "while"
indent.ctrlSite = 2
// identation of definition of parameters in cls and fce
indent.defnSite = 2
// indentation of "extends" and "with"
indent.extendSite = 2
// indent nested match and infix expressions
// this causes issues with // comments, indents them
// indent.relativeToLhsLastLine = [match, infix]
// indentation of multiline nested parentheses
binPack.indentCallSiteOnce = false
binPack.indentCallSiteSingleArg = false


// ---------------------
// indent operator
// ---------------------
// apply indentation exempts only in some cases
//indentOperator.preset = "spray"
// exempt indentation of 2nd and additional lines in special cases
indentOperator.exemptScope = all


// ---------------------
// new lines
// ---------------------
// remove line breaks, leads to horizontal code
//newlines.source = fold
// newlines around statements
newlines.topLevelStatementBlankLines = [
{
blanks = 1
}
{
minBreaks = 1
blanks = 1
}
]
// newlines after package, class, trait header if body is not trivial
newlines.topLevelBodyIfMinStatements = []
newlines.topLevelBodyMinStatements = 2
newlines.beforeTemplateBodyIfBreakInParentCtors = true
// force newline in case/if/while when the body is multiline
newlines.beforeMultiline = keep
newlines.alwaysBeforeElseAfterCurlyIf = false
// break when assignment is multiline
// newlines.forceBeforeMultilineAssign = any
// formatting of bounds of type parameters: upper <:, lower >:, view <%, and context : bounds
newlines.beforeTypeBounds = unfold
// newlines in { case ... => f() } lambdas
// newlines.beforeCurlyLambdaParams = never
// newlines.afterCurlyLambdaParams = squash
// spaces after implicit in fce parameter list
//newlines.implicitParamListModifierForce = [after]
//newlines.avoidForSimpleOverflow = [punct, tooLong, slc]
// skip newlines in the result type
newlines.avoidInResultType = true
// don't put newline before : of the result type if line overflows
newlines.sometimesBeforeColonInMethodReturnType = false
// chains of calls
newlines.selectChains = keep
// in interpolation
newlines.inInterpolation = avoid
// dangling parenteses
danglingParentheses.preset = true
danglingParentheses.exclude = []

// config style arguments
//optIn.configStyleArguments = true
//runner.optimizer.forceConfigStyleOnOffset = 80
//runner.optimizer.forceConfigStyleMinArgCount = 1


// rewrite rules
// - drop redundant braces like { } around a block
// - drop redundant parentheses like ( ) around a statement
// - sort implicit final private lazy
// - prefer for { } yield () over for (;) yield ()
// - organize imports
rewrite.rules = [RedundantBraces, RedundantParens, SortModifiers, PreferCurlyFors, Imports]
rewrite.redundantBraces.stringInterpolation = true
rewrite.imports.sort = scalastyle
rewrite.trailingCommas.style = always
// rewrite tokens to different characters
rewriteTokens = {
"⇒": "=>"
"→": "->"
"←": "<-"
}

// vertical align a line breaks
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineAfterOpenParen = true

// wrap long standalone comments
comments.wrap = standalone
comments.wrapStandaloneSlcAsSlc = true

// javadoc formatting
docstrings.style = SpaceAsterisk
docstrings.blankFirstLine = yes
docstrings.removeEmpty = true
docstrings.oneline = fold
docstrings.wrapMaxColumn = 80

// all calls in chains start on a new line
includeNoParensInSelectChains = true
// keep chains on multiple lines if already multiline
optIn.breakChainOnFirstMethodDot = true

// scala 3 config
rewrite.scala3.convertToNewSyntax = true
//rewrite.trailingCommas.style = "multiple"
38 changes: 30 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import org.typelevel.sbt.tpolecat.DevMode
import sbt.Keys._
import sbt._
import org.typelevel.scalacoptions._

normalizedName := "play-redis"

Expand All @@ -17,25 +19,25 @@ playVersion := "2.9.0"

libraryDependencies ++= Seq(
// play framework cache API
"com.typesafe.play" %% "play-cache" % playVersion.value % Provided,
"com.typesafe.play" %% "play-cache" % playVersion.value % Provided,
// redis connector
"io.github.rediscala" %% "rediscala" % "1.14.0-akka",
"io.github.rediscala" %% "rediscala" % "1.14.0-akka",
// test framework with mockito extension
"org.scalatest" %% "scalatest" % "3.2.17" % Test,
"org.scalamock" %% "scalamock" % "5.2.0" % Test,
"org.scalatest" %% "scalatest" % "3.2.17" % Test,
"org.scalamock" %% "scalamock" % "5.2.0" % Test,
// test module for play framework
"com.typesafe.play" %% "play-test" % playVersion.value % Test,
"com.typesafe.play" %% "play-test" % playVersion.value % Test,
// to run integration tests
"com.dimafeng" %% "testcontainers-scala-core" % "0.41.2" % Test
"com.dimafeng" %% "testcontainers-scala-core" % "0.41.2" % Test,
)

resolvers ++= Seq(
"Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/"
"Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/",
)

javacOptions ++= Seq("-Xlint:unchecked", "-encoding", "UTF-8")

scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked")
scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked", "-Ywarn-unused")

enablePlugins(CustomReleasePlugin)

Expand All @@ -44,6 +46,11 @@ coverageExcludedFiles := ".*exceptions.*"

Test / test := (Test / testOnly).toTask(" * -- -l \"org.scalatest.Ignore\"").value

semanticdbEnabled := true
semanticdbOptions += "-P:semanticdb:synthetics:on"
semanticdbVersion := scalafixSemanticdb.revision
ThisBuild / scalafixScalaBinaryVersion := CrossVersion.binaryScalaVersion(scalaVersion.value)

wartremoverWarnings ++= Warts.allBut(
Wart.Any,
Wart.AnyVal,
Expand All @@ -66,3 +73,18 @@ wartremoverWarnings ++= Warts.allBut(
Wart.TryPartial,
Wart.Var,
)

tpolecatDevModeOptions ~= { opts =>
opts.filterNot(Set(ScalacOptions.warnError))
}

Test / tpolecatExcludeOptions ++= Set(
ScalacOptions.warnValueDiscard,
ScalacOptions.warnNonUnitStatement,
)

ThisBuild / tpolecatCiModeEnvVar := "CI"
ThisBuild / tpolecatDefaultOptionsMode := DevMode

addCommandAlias("fix", "; scalafixAll; scalafmtAll; scalafmtSbt")
addCommandAlias("lint", "; scalafmtSbtCheck; scalafmtCheckAll; scalafixAll --check")
32 changes: 16 additions & 16 deletions project/CustomReleasePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,37 @@ object CustomReleasePlugin extends AutoPlugin {

override def requires: Plugins = ReleasePlugin && GitVersioning && Sonatype

private def customizedReleaseProcess: Seq[ReleaseStep] = {
private def customizedReleaseProcess: Seq[ReleaseStep] =
Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
DocumentationUpdate.updateDocumentation,
)
}

override def projectSettings: Seq[Setting[_]] = Seq[Setting[_]](
publishMavenStyle := true,
pomIncludeRepository := { _ => false },
override def projectSettings: Seq[Setting[?]] = Seq[Setting[?]](
publishMavenStyle := true,
pomIncludeRepository := { _ => false },
// customized release process
releaseProcess := customizedReleaseProcess,
releaseProcess := customizedReleaseProcess,
// release details
homepage := Some(url("https://github.com/karelcemus/play-redis")),
licenses := Seq("Apache 2" -> url("https://www.apache.org/licenses/LICENSE-2.0")),
scmInfo := Some(
homepage := Some(url("https://github.com/karelcemus/play-redis")),
licenses := Seq("Apache 2" -> url("https://www.apache.org/licenses/LICENSE-2.0")),
scmInfo := Some(
ScmInfo(
url("https://github.com/KarelCemus/play-i18n.git"),
"scm:[email protected]:KarelCemus/play-i18n.git"
)
"scm:[email protected]:KarelCemus/play-i18n.git",
),
),
developers := List(
Developer(id = "karel.cemus", name = "Karel Cemus", email = "", url = url("https://github.com/KarelCemus/"))
developers := List(
Developer(id = "karel.cemus", name = "Karel Cemus", email = "", url = url("https://github.com/KarelCemus/")),
),
// Publish settings
publishTo := sonatypePublishToBundle.value,
publishTo := sonatypePublishToBundle.value,
// git tags without "v" prefix
SbtGit.git.gitTagToVersionNumber := { tag: String =>
if (tag matches "[0-9]+\\..*") Some(tag)
else None
}
},
)

private lazy val inquireVersions: ReleaseStep = { implicit st: State =>
Expand All @@ -65,9 +64,10 @@ object CustomReleasePlugin extends AutoPlugin {

st.log.info("Press enter to use the default value")

//flatten the Option[Option[String]] as the get returns an Option, and the value inside is an Option
// flatten the Option[Option[String]] as the get returns an Option, and the value inside is an Option
val releaseV = readVersion(suggestedReleaseV, "Release version [%s] : ", useDefs, st.get(ReleaseKeys.commandLineReleaseVersion).flatten)

st.put(ReleaseKeys.versions, (releaseV, releaseV))
}

}
10 changes: 5 additions & 5 deletions project/DocumentationUpdate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ object DocumentationUpdate {
private def artifactId(implicit st: State) = st.extracted.get(normalizedName)

/** SBT dependency definition */
private def sbtDependency(version: String)(implicit st: State) = {
private def sbtDependency(version: String)(implicit st: State) =
s""" "$groupId" %% "$artifactId" % "$version" """.trim
}

/** Major and minor version of Play framework */
private def playMinorVersion(implicit st: State) = {
Expand All @@ -45,16 +44,16 @@ object DocumentationUpdate {
def replacement(version: String)(implicit st: State) = s"<!-- Play $playMinorVersion -->$version<!-- / -->"
}

def updateDocumentation: ReleaseStep = ReleaseStep({ implicit st: State =>
def updateDocumentation: ReleaseStep = ReleaseStep { implicit st: State =>
val commitMessage = s"Documentation updated to version $next"
val program = List[State => State](
bumpVersionInDoc(_),
bumpLatestVersionInReadme(_),
commitVersion(commitMessage)(_)
commitVersion(commitMessage)(_),
).reduce(_ andThen _)

program(st)
})
}

private def bumpVersionInDoc(implicit st: State): State = {
val latest = vcs.latest
Expand Down Expand Up @@ -99,4 +98,5 @@ object DocumentationUpdate {
}
newState
}

}
Loading

0 comments on commit 0042f4e

Please sign in to comment.