Code Monkey home page Code Monkey logo

sbt-tpolecat's Introduction

sbt-tpolecat

Build Status License Latest Version

scalac options for the enlightened

sbt-tpolecat is an SBT plugin for automagically configuring scalac options according to the project Scala version, inspired by Rob Norris (@tpolecat)'s excellent series of blog posts providing recommended options to get the most out of the compiler.

As of version 0.1.11, it also supports setting options for Scala 3.x.

Usage

Add the following to your project's project/plugins.sbt:

addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.0")

Once you are using this plugin we recommend that you don't manipulate the scalacOptions key directly.

Instead you should modify the tpolecatScalacOptions key or the options key for the relevant mode, for example tpolecatDevModeOptions for the development mode.

Excluding specific warnings

To exclude an individual warning, say to ignore unused imports during testing, you can add the following to your configuration:

import org.typelevel.scalacoptions.ScalacOptions

Test / tpolecatExcludeOptions += ScalacOptions.warnUnusedImports

If you would like to exclude more than one warning, you can add a Set of scalac options, like so:

import org.typelevel.scalacoptions.ScalacOptions

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

ScalaTest warnings

One of the options configured by sbt-tpolecat (-Wnonunit-statement) is designed to warn users about discarded values in their code.

However, Scalatest assertions return a value of type Assertion by design, in order to support async testing.

Unfortunately, this means that in synchronous test suites, every assertion discards this Assertion value, triggering the -Wnonunit-statement compiler warning.

If you find yourself in this situation, you can disable the -Wnonunit-statement option in your test suite like so:

import org.typelevel.scalacoptions.ScalacOptions

Test / tpolecatExcludeOptions += ScalacOptions.warnNonUnitStatement

Configuring the REPL

To filter out scala compiler options that don't work well in the REPL, use the tpolecatExcludeOptions.

By default, the plugin only applies this filter to the console task in the Compile and Test configurations.

For example, to apply this filter to the console task in the IntegrationTest configuration you can do the following:

IntegrationTest / console / tpolecatExcludeOptions ++= ScalacOptions.defaultConsoleExclude

Modes

This plugin can be used in several modes. The default mode is the continuous integration mode.

Modes can be selected by using mode switching commands, or by setting environment variables.

When multiple mode-setting environment variables are defined, the most restrictive mode is selected. For example, if the SBT_TPOLECAT_DEV and SBT_TPOLECAT_CI variables are both defined, continuous integration mode will be enabled.

You can customise the default mode by modifying the ThisBuild / tpolecatDefaultOptionsMode key. Default: CiMode.

Development mode

To enable the development mode, use the tpolecatDevMode command or define the environment variable SBT_TPOLECAT_DEV.

In this mode a baseline set of scala compiler options are enabled.

You can customise the options that are enabled in this mode by modifying the tpolecatDevModeOptions key. Default: ScalacOptions.default.

For example, to disable macros you could customise the development mode options as follows:

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

You can customise the environment variable that is used to enable this mode by modifying the ThisBuild / tpolecatDevModeEnvVar key. Default: "SBT_TPOLECAT_DEV".

Verbose mode

To enable the verbose mode, use the tpolecatVerboseMode command or define the environment variable SBT_TPOLECAT_VERBOSE.

In this mode all development mode options are enabled, and several verbose options that are commonly used for debugging implicit resolution and providing detailed compile errors are enabled.

You can customise the options that are enabled in this mode by modifying the tpolecatVerboseModeOptions key. Default: tpolecatDevModeOptions.value ++ ScalacOptions.verboseOptions.

For example, to disable verbose implicit logging you could customise the verbose mode options as follows:

tpolecatVerboseModeOptions ~= { opts =>
  opts.filterNot(Set(ScalacOptions.verboseImplicits))
}

You can customise the environment variable that is used to enable this mode by modifying the ThisBuild / tpolecatVerboseModeEnvVar key. Default: "SBT_TPOLECAT_VERBOSE".

Continuous integration mode

To enable the continuous integration mode, use the tpolecatCiMode command or define the environment variable SBT_TPOLECAT_CI.

In this mode all development mode options are enabled, and the fatal warnings option (-Xfatal-warnings ) is added.

You can customise the options that are enabled in this mode by modifying the tpolecatCiModeOptions key. Default: tpolecatDevModeOptions.value + ScalacOptions.fatalWarnings.

For example, to disable unused linting you could customise the CI options as follows:

tpolecatCiModeOptions ~= { opts =>
  opts.filterNot(
    ScalacOptions.privateWarnUnusedOptions ++
      ScalacOptions.warnUnusedOptions
  )
}

You can customise the environment variable that is used to enable this mode by modifying the ThisBuild / tpolecatCiModeEnvVar key. Default: "SBT_TPOLECAT_CI".

Release mode

To enable the release mode, use the tpolecatReleaseMode command or define the environment variable SBT_TPOLECAT_RELEASE.

In this mode all CI mode options are enabled, and the method-local optimisation option (-opt:l:method) is enabled if available for your Scala version.

You can customise the options that are enabled in this mode by modifying the tpolecatReleaseModeOptions key. Default: tpolecatCiModeOptions.value + ScalacOptions.optimizerMethodLocal.

For example, to enable inlining within your library or application's packages you could customise the release options as follows:

tpolecatReleaseModeOptions ++= ScalacOptions.optimizerOptions("your.library.**")

To understand more about the Scala optimizer read The Scala 2.12 / 2.13 Inliner and Optimizer.

You can customise the environment variable that is used to enable this mode by modifying the ThisBuild / tpolecatReleaseModeEnvVar key. Default: "SBT_TPOLECAT_RELEASE".

Caveat

I can't promise this plugin will work for old minor releases of Scala.

It is currently tested with Scala 2.x releases:

  • 2.13.8
  • 2.12.16
  • 2.11.12

and Scala 3.x releases:

  • 3.0.2
  • 3.1.3
  • 3.3.0
  • 3.3.1

Conduct

Participants are expected to follow the Scala Code of Conduct while discussing the project on GitHub and any other venues associated with the project.

License

All code in this repository is licensed under the Apache License, Version 2.0. See LICENSE.

sbt-tpolecat's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sbt-tpolecat's Issues

Scala.js options overwritten on Scala 3

On Scala 3, -scalajs option is required to generate IR files. Without it, the compiler will complain, and the linking will succeed without actually doing anything.

In the app you will likely notice it immediately, in the libraries - not so much.

Desired behaviour: -scalajs option, if present, is preserved

───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: ./Test.scala
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1@main def hello = println("yo")
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: ./project/plugins.sbt
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat"              % "0.4.1")
   2   │ addSbtPlugin("org.scala-js"              % "sbt-scalajs"               % "1.10.1")
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: ./build.sbt
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ scalaVersion := "3.1.3"
   23   │ enablePlugins(ScalaJSPlugin)
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/v/f/m/d/T/tmp.B2Uwm0IW > sbt run
[info] welcome to sbt 1.6.2 (GraalVM Community Java 17.0.3)
[info] loading global plugins from /Users/velvetbaldmime/.sbt/1.0/plugins
...
[warn] The `-scalajs` flag was missing from `compile / scalacOptions`, but it is required to produce Scala.js IR.
[warn] Linking, running and/or testing will probably go wrong.
[warn] The most likely cause is that you used `scalacOptions := ...` instead of using `++=`.

warnUnused is reporting on Assertions

Hello, since 0.4.2 I am seeing Scalatest tests reporting unused on assertions that aren't the final value in a test, e.g.

  // ... rest of test
  config.topicLoader.idleTimeout shouldBe 1.second // This errors
  config.topicLoader.bufferSize.value shouldBe 10 // This errors too
  config.topicLoader.clientId.value shouldBe "test-client-id" // This is fine
}
/src/test/scala/unit/ConfigSpec.scala:113:38: unused value of type org.scalatest.Assertion (add `: Unit` to discard silently)
[error]       config.topicLoader.idleTimeout shouldBe 1.second 

I have tried disabling scalaFix in case it was conflicting but no change.

Is this intended behaviour?

Tag release version in git?

Often times we rely on git-tag-release as a notification that a new version of the software is available. Most of the github project follow this convention

Set every tpolecatOptionsMode with tpolecatDevMode

We have a multi-project build and just updated to the latest version of this plugin. Some really nice changes!

We still have a few projects with warnings so cannot have CiMode enabled on everything.

We set ThisBuild / tpolecatDefaultOptionsMode := DevMode to disable fatal warnings and then set tpolecatOptionsMode := CiMode on the individual projects which have no warnings.

This is great except that it doesn't work very well with tpolecatDevMode as that only sets the build scoped setting.

Can we change it to this instead?

set every tpolecatOptionsMode := _root_.io.github.davidgregory084.DevMode

Seems to work in my local testing.

`-source` choices passed to scalac 3.* via space instead of colon and gets ignored.

scalac respects -source option choices only if they are passed via colon to it: -source:future, -source:future-migration, etc.

As far as I could understand, sbt-tpolecat passes all options along with arguments to scalac as one big List[String] turn lead to ignore or such options.

Could be shown with this scala-cli scripts:

  1. Working one:

    //> using scala "3.2.1"
    //> using option "-source:future"
    
    def method[A: Numeric](a: A): A => A = { a1 =>
      implicitly[Numeric[A]].plus(a, a1)
    }
    
    println(s"method(1)(1) = ${method(1)(1)}")
  2. Incorrect:

    //> using scala "3.2.1"
    //> using option "-source future"
    
    def method[A: Numeric](a: A): A => A = { a1 =>
      implicitly[Numeric[A]].plus(a, a1)
    }
    
    println(s"method(1)(1) = ${method(1)(1)}")

    Compilation fails with:

    Compiling project (Scala 3.2.1, JVM)
    Warning: bad option '-source future' was ignored
    [error] ./space.sc:9:38
    [error] Found:    (1 : Int)
    [error] Required: Numeric[Int]
    [error] println(s"method(1)(1) = ${method(1)(1)}")
    [error]                                      ^
    Error compiling project (Scala 3.2.1, JVM)
    Compilation failed

P.S. the same could be said about -Ykind-projector:underscores and other : options.

Cannot import sbt-tpolecat in other plugin as a required dependency

I have a project which uses an internal SBT Plugin, which further contains a lot of common build settings, dependencies etc.

The definition for this Plugin looks like this:

import org.scalafmt.sbt.ScalafmtPlugin
import org.scalastyle.sbt.ScalastylePlugin
import scoverage.ScoverageSbtPlugin

object MyPlugin extends AutoPlugin {
  override def requires: Plugins =
    ScalafmtPlugin && ScalastylePlugin && ScoverageSbtPlugin

and they are added in build.sbt in the project settings as:

addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.3"),
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0"),
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.1"),

Issue:
I have added:

addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.20"),

and it is imported correctly, but I cannot programmatically use it's definition, because

import io.github.davidgregory084.TpolecatPlugin

cannot be properly resolved.
And as far as I see, and IntelliJ helps me here. it is because it starts with io which is an internal SBT package.
And for some reason, it is hidden behind this package.

Tbh, I don't know if there is some walkaround...
But it seems to me that io.github might be a very unfortunate prefix :(

Error code:

[error] ...sbt/MyPlugin.scala:11:11: object github is not a member of package sbt.io
[error] import io.github.davidgregory084.TpolecatPlugin

Unable to use `-source:3.0-migration`

Using latest (0.1.19) version of the plugin, I cannot use -source:3.0-migration as the -source future flag is already added (since #42).

Example:

scalacOptions ++= {
  if (scalaVersion.value.startsWith("3."))
    Seq("-source:3.0-migration")
  else
    Seq()
}

Error:

[error] Flag -source set repeatedly
[error] one error found
[error] (core / Compile / compileIncremental) Compilation failed
[error] Total time: 0 s, completed May 30, 2021, 5:04:23 PM

@2m was right about #42 (comment)

Tut not found

README recommends this:

scalacOptions.in(Tut) ~= filterConsoleScalacOptions

please use some actual configuration? Also, I'd suggest switching to the / syntax.

-explain-types generates far too much output

I was trying to upgrade a project from scala-2 to -3, and having to do it manually (scala3-migrate was gagging on ScalaFX code). The compiler was generating so much output (from code that compiled totally cleanly in Scala-2) and the explain-types code is so large compared to the actual error messages that I could not use a full screen console to see more than 1 error per scroll, and I think (unproven) that this was taking so long to generate and send that when metals trys to start sbt it times out.

I know the compiler is trying to be helpful, but one does need to be able to see the wood for the trees!

Please remove this option (at least for now) along with -explain (both seen to be needed to be removed to clean up the output)

Error when enabling scalafix in multi project build on versions > 0.3.1

Hello. I have encountered compile error when enabling scalafix on multi project build on versions > 0.3.1.

Error:

[error] bad option: -P:semanticdb:targetroot:${project_dir}/module1/target/scala-2.13/meta

build.sbt

import _root_.io.github.davidgregory084.ScalacOptions

ThisBuild / scalaVersion := "2.13.8"
ThisBuild / semanticdbEnabled := true
ThisBuild / semanticdbVersion := scalafixSemanticdb.revision

lazy val commonSettings = 
  Seq(
    Compile / tpolecatScalacOptions := Set()
  )

lazy val module1 = (project in file("module1"))
  .settings(name := "module1")
  .settings(commonSettings)

lazy val module2 = (project in file("module2"))
  .settings(name := "module2")
  .settings(commonSettings)

lazy val root = (project in file("."))
  .settings(name := "root")
  .aggregate(module1, module2)

Global / onChangedBuildSource := ReloadOnSourceChanges

Minimal example:
https://github.com/artogai/tpolecat-scalameta

CI matrix build is testing the wrong versions

In #76 I very cleverly wrote a test that relies on Java 9+ and then expected it to work on the CI crossbuild. This failed immediately, but only on the "Release" job, which specified "temurin@8".

However, this has revealed to me that the current crossbuild is silently installing wrong Java versions - it seems that the setup-scala action just picks a random feature of the version number to match on so for 8 it is installing 1.11.0-8.

Just making a note reminding myself to finish up #71 ASAP.

Change in assignment to `scalacOptions` key ignores any build specific options

The problem is with following code in io.github.davidgregory084.TpolecatPlugin in latest 0.2.2 version.

  override def projectSettings: Seq[Setting[_]] = Seq(
    Def.derive(
      scalacOptions := scalacOptionsFor(scalaVersion.value, tpolecatScalacOptions.value)
    ),

and scalacOptions is now set a value via := instead of being added ++= as it was done in version 0.1.22 for example.

This results in ignoring any user specified scalacOptions in ThisBuild scope.

ThisBuild / scalacOptions ++= Seq(...)

Is there a reason of not using ++= instead of :=?

ScalacOption case class unreachable from build.sbt

In order to use ScalacOption you need to import it via the _root_.io.github.davidgregory084.ScalacOption otherwise sbt looks for it in sbt.io.github.davidgregory084.ScalacOption.

Using it is useful for undefined DSL scalacOptions

Consider adding -Ywarn-macros:after

This flag reduces a lot of false positives, especially when some implicits are used inside a macro expansion. Circe is a common case for such a problem.
Also, as far as I know, there is no downside on adding it.

Scala 2.13 support

It would be nice if this also worked on the latest milestone of Scala 2.13 (currently 2.13.0-M4). To make it work in my project I had to add:

scalacOptions in Compile := {
  val invalidOptions = CrossVersion.partialVersion(scalaVersion.value) match {
    case Some((2, 13)) => Set("-Yno-adapted-args", "-Ypartial-unification")
    case _ => Set.empty[String]
  }
  scalacOptions.value.filterNot(invalidOptions)
}

Optionally disable `-Xfatal-warnings`?

Would you be open to adding some config to disable -Xfatal-warnings?

Background: I wrote a plugin for "strict scope", where you can run e.g. strict test to run test with fatal warnings enabled. It's handy so you can have nonfatal warnings by default, but run with fatal warnings for precommit / CI: https://github.com/timbertson/sbt-strict-scope

I love this plugin in general, but it ends up meaning I need to fight it by adding scalacOptions ~= (_ filterNot (_ == "-Xfatal-warnings")) to all of my projects. It's a oneliner, but not exactly easy to remember.

Would you be open to adding a scalacFatalWarnings := false or similar key in this plugin to cover this kind of use case?

I could add it in my plugin, but honestly I'm not that confident about it working properly depending on plugin load order, so it'd be great if it could live in this plugin.

a number of options are being set in (Compile, doc)

sbt> show doc / scalacOptions
[info] * -encoding
[info] * utf8
[info] * -deprecation
[info] * -explaintypes
[info] * -feature
[info] * -language:existentials
[info] * -language:experimental.macros
[info] * -language:higherKinds
[info] * -language:implicitConversions
[info] * -unchecked
[info] * -Xcheckinit
[info] * -Xfatal-warnings
[info] * -Xlint:adapted-args
[info] * -Xlint:by-name-right-associative
[info] * -Xlint:constant
[info] * -Xlint:delayedinit-select
[info] * -Xlint:doc-detached
[info] * -Xlint:inaccessible
[info] * -Xlint:infer-any
[info] * -Xlint:missing-interpolator
[info] * -Xlint:nullary-override
[info] * -Xlint:nullary-unit
[info] * -Xlint:option-implicit
[info] * -Xlint:package-object-classes
[info] * -Xlint:poly-implicit-overload
[info] * -Xlint:private-shadow
[info] * -Xlint:stars-align
[info] * -Xlint:type-parameter-shadow
[info] * -Xlint:unsound-match
[info] * -Yno-adapted-args
[info] * -Ywarn-dead-code
[info] * -Ywarn-extra-implicit
[info] * -Ywarn-nullary-override
[info] * -Ywarn-nullary-unit
[info] * -Ywarn-numeric-widen
[info] * -Ywarn-unused:implicits
[info] * -Ywarn-unused:imports
[info] * -Ywarn-unused:locals
[info] * -Ywarn-unused:params
[info] * -Ywarn-unused:patvars
[info] * -Ywarn-unused:privates
[info] * -Ypartial-unification
[info] * -Xplugin:/Users/yurique/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-compiler_2.12.12/1.3.1/scalajs-compiler_2.12.12-1.3.1.jar

when publishing, this results in warnings:

[warn] bad option '-scalajs' was ignored
[warn] bad option '-deprecation' was ignored
[warn] bad option '-explain-types' was ignored
[warn] bad option '-explain' was ignored
[warn] bad option '-feature' was ignored
[warn] bad option '-language:existentials,experimental.macros,higherKinds,implicitConversions' was ignored
[warn] bad option '-unchecked' was ignored
[warn] bad option '-Xfatal-warnings' was ignored
[warn] bad option '-Ykind-projector' was ignored
[warn] bad option '-from-tasty' was ignored
[warn] bad option '-no-link-warnings' was ignored
[warn] Setting -encoding is currently not supported.

without the plugin:

sbt> show doc / scalacOptions
[info] * -Xplugin:/Users/yurique/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-compiler_2.13.4/1.3.1/scalajs-compiler_2.13.4-1.3.1.jar

Extract settings DSL into a library

Briefly discussed on the Discord. This would allow sharing with the mill version of this plugin, and would also open the door for e.g. sbt-typelevel-settings to reuse this while integrating with sbt in a different way. Essentially I think it would be extracting the "unopinionated" part of this plugin from the "opinionated" :P

Change modes in intellij

Is there a way to change to development mode when building a project with Intellij?

I've been able to change to development mode when using the sbt console with environment variables or sbt commands but this doesn't work when doing Build > Build Project from the intellij UI.
It would be nice to be able to do this to not have to worry about unused variables or imports when developing.

Mill support

I need to have something like that for Mill build tool.

How could we approach that problem? Is this something that you would consider merging into this repository or should I fork it?

`tpolecatOptionsMode` is ignored in test scope

In my build.sbt file I have tpolecat settings defined as following

lazy val tpolecatSettings = Seq(
  Compile / tpolecatOptionsMode := ReleaseMode,
  Compile / tpolecatScalacOptions ++= Set(
    new ScalacOption(List("-Ypatmat-exhaust-depth", "off")),
    ScalacOptions.warnOption("""conf:cat=deprecation&site=com\.foo\.bar\..*:s""")
  ),
  Compile / doc / tpolecatOptionsMode := DevMode,
  Test / tpolecatOptionsMode := DevMode
)

which are then added to a project.
In version 0.2.2 it worked as expected: fatal-warnings was present in compile scope but absent in test scope(as it is defined in tpolecatScalacOptions for DevMode and ReleaseMode).
Then I changed the plugin version to 0.2.3 and test scope started to have fatal-warnings, meaning that sbt test fails due to compilation errors, because there are warnings in test scope. I also tried the most recent version of the plugin(0.3.1 at the moment of creating this issue), the result is the same.

Output of inspect Test/tpolecatScalacOptions when using plugin version 0.2.3

sbt:server> inspect Test/tpolecatScalacOptions
[info] Setting: scala.collection.immutable.Set[io.github.davidgregory084.ScalacOption] = ListSet(ScalacOption(-encoding utf8), ScalacOption(-deprecation), ScalacOption(-feature), ScalacOption(-unchecked), ScalacOption(-language:existentials), ScalacOption(-language:experimental.macros), ScalacOption(-language:higherKinds), ScalacOption(-language:implicitConversions), ScalacOption(-Xcheckinit), ScalacOption(-Xlint), ScalacOption(-Xlint:adapted-args), ScalacOption(-Xlint:by-name-right-associative), ScalacOption(-Xlint:constant), ScalacOption(-Xlint:delayedinit-select), ScalacOption(-Xlint:deprecation), ScalacOption(-Xlint:doc-detached), ScalacOption(-Xlint:implicit-recursion), ScalacOption(-Xlint:implicit-not-found), ScalacOption(-Xlint:inaccessible), ScalacOption(-Xlint:infer-any), ScalacOption(-Xlint:missing-interpolator), ScalacOption(-Xlint:nullary-override), ScalacOption(-Xlint:nullary-unit), ScalacOption(-Xlint:option-implicit), ScalacOption(-Xlint:package-object-classes), ScalacOption(-Xlint:poly-implicit-overload), ScalacOption(-Xlint:private-shadow), ScalacOption(-Xlint:stars-align), ScalacOption(-Xlint:strict-unsealed-patmat), ScalacOption(-Xlint:type-parameter-shadow), ScalacOption(-Xlint:unsound-match), ScalacOption(-Xlint:-byname-implicit), ScalacOption(-Yno-adapted-args), ScalacOption(-Ykind-projector), ScalacOption(-Ywarn-dead-code), ScalacOption(-Ywarn-extra-implicit), ScalacOption(-Ywarn-inaccessible), ScalacOption(-Ywarn-nullary-override), ScalacOption(-Ywarn-nullary-unit), ScalacOption(-Ywarn-numeric-widen), ScalacOption(-Ywarn-unused), ScalacOption(-Ywarn-unused-import), ScalacOption(-Ywarn-value-discard), ScalacOption(-Ywarn-unused:implicits), ScalacOption(-Ywarn-unused:imports), ScalacOption(-Ywarn-unused:locals), ScalacOption(-Ywarn-unused:params), ScalacOption(-Ywarn-unused:patvars), ScalacOption(-Ywarn-unused:privates), ScalacOption(-Wdead-code), ScalacOption(-Wextra-implicit), ScalacOption(-Wnumeric-widen), ScalacOption(-Wvalue-discard), ScalacOption(-Wunused:nowarn), ScalacOption(-Wunused:implicits), ScalacOption(-Wunused:explicits), ScalacOption(-Wunused:imports), ScalacOption(-Wunused:locals), ScalacOption(-Wunused:params), ScalacOption(-Wunused:patvars), ScalacOption(-Wunused:privates))
[info] Description:
[info]  The set of scalac options that will be applied by the sbt-tpolecat plugin.
[info] Provided by:
[info]  ProjectRef(uri("file:/home/mbesida/myproject/"), "root") / Test / tpolecatScalacOptions
[info] Defined at:
[info]  (io.github.davidgregory084.TpolecatPlugin.projectSettings) TpolecatPlugin.scala:141
[info] Dependencies (D=derived from):
[info]  D Test / tpolecatReleaseModeOptions
[info]  D Test / tpolecatCiModeOptions
[info]  D Test / tpolecatDevModeOptions
[info]  D Test / tpolecatOptionsMode
[info] Reverse dependencies (D=derives):
[info]  D Test / scalacOptions
[info] Delegates:
[info]  Test / tpolecatScalacOptions
[info]  Runtime / tpolecatScalacOptions
[info]  Compile / tpolecatScalacOptions
[info]  tpolecatScalacOptions
[info]  ThisBuild / Test / tpolecatScalacOptions
[info]  ThisBuild / Runtime / tpolecatScalacOptions
[info]  ThisBuild / Compile / tpolecatScalacOptions
[info]  ThisBuild / tpolecatScalacOptions
[info]  Zero / Test / tpolecatScalacOptions
[info]  Zero / Runtime / tpolecatScalacOptions
[info]  Zero / Compile / tpolecatScalacOptions
[info]  Global / tpolecatScalacOptions
[info] Related:
[info]  Compile / doc / tpolecatScalacOptions
[info]  tasks / Test / tpolecatScalacOptions
[info]  common / Test / console / tpolecatScalacOptions
[info]  common / Compile / console / tpolecatScalacOptions
[info]  tasks / Compile / console / tpolecatScalacOptions
[info]  tasks / Compile / doc / tpolecatScalacOptions
[info]  serverApi / Test / console / tpolecatScalacOptions
[info]  serverApi / Compile / console / tpolecatScalacOptions
[info]  common / Compile / tpolecatScalacOptions
[info]  Compile / console / tpolecatScalacOptions
[info] ...

Output of inspect tree Test/tpolecatScalacOptions when using plugin version 0.2.3

sbt:server> inspect tree Test/tpolecatScalacOptions
[info] Test / tpolecatScalacOptions = ListSet(ScalacOption(-encoding utf8), ScalacOpt..
[info]   +-tpolecatCiModeOptions = ListSet(ScalacOption(-encoding utf8), ScalacOption..
[info]   +-tpolecatDevModeOptions = ListSet(ScalacOption(-encoding utf8), ScalacOptio..
[info]   +-Test / tpolecatOptionsMode = DevMode
[info]   +-tpolecatReleaseModeOptions = ListSet(ScalacOption(-encoding utf8), ScalacO..
[info]   

Output of inspect Test/tpolecatScalacOptions when using plugin version 0.2.2

sbt:server> inspect Test/tpolecatScalacOptions
[info] Setting: scala.collection.immutable.Set[io.github.davidgregory084.ScalacOption] = ListSet(ScalacOption(-encoding utf8), ScalacOption(-deprecation), ScalacOption(-feature), ScalacOption(-unchecked), ScalacOption(-language:existentials), ScalacOption(-language:experimental.macros), ScalacOption(-language:higherKinds), ScalacOption(-language:implicitConversions), ScalacOption(-Xcheckinit), ScalacOption(-Xlint), ScalacOption(-Xlint:adapted-args), ScalacOption(-Xlint:by-name-right-associative), ScalacOption(-Xlint:constant), ScalacOption(-Xlint:delayedinit-select), ScalacOption(-Xlint:deprecation), ScalacOption(-Xlint:doc-detached), ScalacOption(-Xlint:implicit-recursion), ScalacOption(-Xlint:implicit-not-found), ScalacOption(-Xlint:inaccessible), ScalacOption(-Xlint:infer-any), ScalacOption(-Xlint:missing-interpolator), ScalacOption(-Xlint:nullary-override), ScalacOption(-Xlint:nullary-unit), ScalacOption(-Xlint:option-implicit), ScalacOption(-Xlint:package-object-classes), ScalacOption(-Xlint:poly-implicit-overload), ScalacOption(-Xlint:private-shadow), ScalacOption(-Xlint:stars-align), ScalacOption(-Xlint:strict-unsealed-patmat), ScalacOption(-Xlint:type-parameter-shadow), ScalacOption(-Xlint:unsound-match), ScalacOption(-Xlint:-byname-implicit), ScalacOption(-Yno-adapted-args), ScalacOption(-Ykind-projector), ScalacOption(-Ywarn-dead-code), ScalacOption(-Ywarn-extra-implicit), ScalacOption(-Ywarn-inaccessible), ScalacOption(-Ywarn-nullary-override), ScalacOption(-Ywarn-nullary-unit), ScalacOption(-Ywarn-numeric-widen), ScalacOption(-Ywarn-unused), ScalacOption(-Ywarn-unused-import), ScalacOption(-Ywarn-value-discard), ScalacOption(-Ywarn-unused:implicits), ScalacOption(-Ywarn-unused:imports), ScalacOption(-Ywarn-unused:locals), ScalacOption(-Ywarn-unused:params), ScalacOption(-Ywarn-unused:patvars), ScalacOption(-Ywarn-unused:privates), ScalacOption(-Wdead-code), ScalacOption(-Wextra-implicit), ScalacOption(-Wnumeric-widen), ScalacOption(-Wvalue-discard), ScalacOption(-Wunused:nowarn), ScalacOption(-Wunused:implicits), ScalacOption(-Wunused:explicits), ScalacOption(-Wunused:imports), ScalacOption(-Wunused:locals), ScalacOption(-Wunused:params), ScalacOption(-Wunused:patvars), ScalacOption(-Wunused:privates))
[info] Description:
[info]  The set of scalac options that will be applied by the sbt-tpolecat plugin.
[info] Provided by:
[info]  ProjectRef(uri("file:/home/mbesida/myproject/"), "root") / Test / tpolecatScalacOptions
[info] Defined at:
[info]  (io.github.davidgregory084.TpolecatPlugin.projectSettings) TpolecatPlugin.scala:141
[info] Dependencies (D=derived from):
[info]  D Test / tpolecatReleaseModeOptions
[info]  D Test / tpolecatCiModeOptions
[info]  D Test / tpolecatDevModeOptions
[info]  D Test / tpolecatOptionsMode
[info] Reverse dependencies (D=derives):
[info]  D Test / scalacOptions
[info] Delegates:
[info]  Test / tpolecatScalacOptions
[info]  Runtime / tpolecatScalacOptions
[info]  Compile / tpolecatScalacOptions
[info]  tpolecatScalacOptions
[info]  ThisBuild / Test / tpolecatScalacOptions
[info]  ThisBuild / Runtime / tpolecatScalacOptions
[info]  ThisBuild / Compile / tpolecatScalacOptions
[info]  ThisBuild / tpolecatScalacOptions
[info]  Zero / Test / tpolecatScalacOptions
[info]  Zero / Runtime / tpolecatScalacOptions
[info]  Zero / Compile / tpolecatScalacOptions
[info]  Global / tpolecatScalacOptions
[info] Related:
[info]  Compile / doc / tpolecatScalacOptions
[info]  tasks / Test / tpolecatScalacOptions
[info]  common / Test / console / tpolecatScalacOptions
[info]  common / Compile / console / tpolecatScalacOptions
[info]  tasks / Compile / console / tpolecatScalacOptions
[info]  tasks / Compile / doc / tpolecatScalacOptions
[info]  serverApi / Test / console / tpolecatScalacOptions
[info]  serverApi / Compile / console / tpolecatScalacOptions
[info]  common / Compile / tpolecatScalacOptions
[info]  Compile / console / tpolecatScalacOptions
[info] ...

PS. I have a multimodule project, but tpolecatSettings are applied to all of them in the same way

warnNonUnitStatement has no effect in Scala 3.3.x

I can see that the option is in the list of ScalacOption in tpolecatScalacOptions, however for some reason I do not get a warning if I have an expression that is unused.

I was able to trigger the warning if I define the compiler flag ("-Wnonunit-statement") directly in scalacOptions.

`utf-8` should be `utf8`

Hi, I'm not using your plugin but I am aware of its existence.

I've recently been victim of this bug scalameta/metals#1303 (as I'm using Rob Norris' flag list on every project). The bug was caused by a bad encoding value : utf-8 should be utf8. Seehere

Kind regards

Invalid filtering for multiple token options

Let's consider those scalac options:

  val parallelismOption = new ScalacOption("-Ybackend-parallelism" :: "8" :: Nil)
  val releaseOption = new ScalacOption("-release" :: "8" :: Nil)

when both added to tpolecatScalacOptions ++= Set(parallelismOption, releaseOption) the resulting scalacOptions is invalid:

[info] * -Ybackend-parallelism
[info] * 8
[info] * -release
[info] * -other-option

This is due to the distinct in

(previous ++ newOptions).filterNot(filters).distinct

Which is applied on individual ScalacOption token instead of the full option.
The filtering logic in the plugin does not handle well the case of multiple token options.

consider not recommending `-Xcheckinit`

it has a performance cost, and lord knows whether it induces correctness issues or not

I would suggest you not recommend it here. personally I would only ever enable it temporarily, during troubleshooting

Warn unused is reporting on XML literals

If I am using scala-xml literals, then I am seeing compile warnings starting with Scala version 2.13.9.

Example:

import scala.xml.Elem

case class ToDoItem(name: String) {
  def toXml: Elem = {
    <to-do-item>
      <name>{name}</name>
    </to-do-item>
  }
}

Compile errors:

[error] ToDoItem.scala:5:5: unused value of type scala.xml.NodeBuffer (add `: Unit` to discard silently)
[error]     <to-do-item>
[error]     ^
[error] /ToDoItem.scala:6:7: unused value of type scala.xml.NodeBuffer (add `: Unit` to discard silently)
[error]       <name>{name}</name>

`-Xcheckinit` should not be enabled by default

For background see:

Now, there's an interesting question here. Since sbt-tpolecat distinguish between Dev, CI, and Release modes, in theory this could be enabled everywhere except Release mode. The problem is that while -Xcheckinit definitely helps catch one category of bugs, to do so it introduces volatiles that could be masking another category of bugs, namely memory visibility issues.

Not specific to this issue, but I think there's a broader question here about CI vs Release modes. The danger with having two distinct modes is that it means you are actually testing something different than what you are shipping, which risks some stuff flying under the radar. I didn't follow the original discussion when these modes were introduced, so I will catch up on some reading now :)

Useful missing DSL flags

When working with Scala 2.13 I find it very useful to have the following list enabled as well in DEV mode:

List(
      "-explaintypes", // Explain type errors in more detail.
      "-Vimplicits", // Enables the tek/splain features to make the compiler print implicit resolution chains when no implicit value can be found
      "-Vtype-diffs", // Enables the tek/splain features to turn type error messages (found: X, required: Y) into colored diffs between the two types
    )

sbt-tpolecat overrides `scalaOutputVersion`

project/build.properties

sbt.version=1.7.0-M2

build.sbt

ThisBuild / scalaVersion       := "3.1.2"
ThisBuild / scalaOutputVersion := "3.0.2"

Gets me:

sbt:sandbox> show scalacOptions
[info] * -scala-output-version
[info] * 3.0
[success] Total time: 0 s, completed Apr 19, 2022, 4:01:09 PM

If I add:
project/plugins.sbt

addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.2.3")

then I get:

sbt:sandbox> show scalacOptions
[info] * -encoding
[info] * utf8
[info] * -deprecation
[info] * -feature
[info] * -unchecked
[info] * -language:experimental.macros
[info] * -language:higherKinds
[info] * -language:implicitConversions
[info] * -Ykind-projector
[info] * -Xfatal-warnings
[success] Total time: 0 s, completed Apr 19, 2022, 4:02:02 PM

Also set `javacOption`

sbt-typelevel-settings currently sets:

javacOptions ++= Seq(
  "-encoding",
  "utf8",
  "-Xlint:all"
),

and

javacOptions ++= {
  if (tlFatalWarnings.value)
    Seq("-Werror")
  else
    Seq.empty
},

I started a PR to add these to sbt-tpolecat. Would the idea be to go all-out and add class JavacOption and stuff?

Proposal: Add -Xlint:implicit-not-found

While the description of the flag doesn't say much:

Check @implicitNotFound and @implicitAmbiguous messages.

What it does is validating that custom implicitNotFound & implicitAmbiguous messages refer to valid type parameters.

// This would warn since there is no T in Foo
@implicitNotFound("No implicit Foo[${T}] found")
trait Foo[A]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.