typelevel / typelevel-scalafix Goto Github PK
View Code? Open in Web Editor NEWScalafix rules for Typelevel projects
License: Apache License 2.0
Scalafix rules for Typelevel projects
License: Apache License 2.0
I suggest adding a linter that will warn for any discarded value, regardless of its type. This would both catch unused effectful code that's not concrete IO
- it would need to be disabled for blocks of side-effecting code, but I see this as an extra advantage since side-effecting code would have to be explicitly marked as such.
Edit: although I guess there is an issue of lazyness here ๐ค
Either.unit
is a Cats syntax and is cached, so saves the allocation.
Code that demands an implicit cats.effect.Spawn[F]
(or a descendant) and also cats.Parallel[F]
could be rewritten to demand only the Spawn[F]
with an import cats.effect.instances.spawn._
.
Version 0.1.5
import cats.effect.Resource
val foo: Resource[A, B] = ???
val x = foo.map(_ => ())
The rule TypelevelAs.as
will complain and suggest to rewrite the map
line to .void
.
Resource
does not have a void
method :)
The check should probably be limited to types that provide the necessary functions.
flatTap
is defined as:
def flatTap[A, B](fa: F[A])(f: A => F[B]): F[A] =
flatMap(fa)(a => as(f(a), a))
While silently discarding an arbitrary B
is convenient for ergonomics, it may be desirable to call attention to the fact you are discarding a result by requiring that B =:= Unit
and thus forcing the user to call .void
if their function does not return F[Unit]
.
This seems like a good candidate for a lint. Inspired by a Discord question, h/t @sbuzzard.
This is a cool rule by @mrdziuban. It's not directly about Cats' types, but a good fit nonetheless ๐
https://github.com/mrdziuban/disable-to-string
h/t @wsargent
Sadly a true deprecation was rejected, but we can still offer a linter for it.
This is an interesting one :)
I (accidentally) ran UnusedIO
against a code base that does not use IO at all.
I cannot share the code but it would appear that throw e
can cause issues.
[error] Caused by: scala.MatchError: throw (e) (of class scala.meta.Term$Throw$TermThrowImpl)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.$anonfun$applyOrElse$2(UnusedIO.scala:68)
[error] at scala.collection.immutable.List.map(List.scala:250)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.applyOrElse(UnusedIO.scala:68)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.applyOrElse(UnusedIO.scala:49)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:338)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:334)
[error] at org.typelevel.fix.UnusedIO.org$typelevel$fix$UnusedIO$$checkInner$1(UnusedIO.scala:76)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.$anonfun$applyOrElse$1(UnusedIO.scala:65)
[error] at scala.collection.immutable.List.map(List.scala:250)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.applyOrElse(UnusedIO.scala:63)
[error] at org.typelevel.fix.UnusedIO$$anonfun$self$lzycompute$1$1.applyOrElse(UnusedIO.scala:49)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:338)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:334)
[error] at org.typelevel.fix.UnusedIO.org$typelevel$fix$UnusedIO$$checkInner$1(UnusedIO.scala:76)
[error] at org.typelevel.fix.UnusedIO.checkDiscardedStat(UnusedIO.scala:79)
[error] at org.typelevel.fix.UnusedIO$$anonfun$checkTree$1.$anonfun$applyOrElse$3(UnusedIO.scala:90)
[error] at scala.collection.immutable.List.map(List.scala:250)
[error] at org.typelevel.fix.UnusedIO$$anonfun$checkTree$1.applyOrElse(UnusedIO.scala:90)
[error] at org.typelevel.fix.UnusedIO$$anonfun$checkTree$1.applyOrElse(UnusedIO.scala:84)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:338)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:334)
[error] at scala.meta.transversers.Api$XtensionCollectionLikeUI$traverser$3$.apply(Api.scala:32)
Since I don't know much about scalafix not sure how hard, or even impossible, this will be...
But, it would be great to warn / error if someone tries to leak a Resource
using pure
or delay
inside use
; which is a somewhat common beginner mistake.
Maybe a best effort that tries to catch common variations like ra.use(a => a.pure[F])
or ra.use(IO.apply)
can be enough?
Another idea would be to warn if use
returns an F[A]
rather than some F[B]
(meaning the same type of the Resource
), since on the surface it seems that would never be a good idea; but I may be being too naive.
As we acquire more rules it might be better to set up a website with different pages and/or table-of-contents for the various modules to help navigate it all
I am writing tests using munit.CatsEffectSuite
and using typelevel-scalafix v0.1.3
.
import munit.CatsEffectSuite
final class MySuite extends CatsEffectSuite {
test("foo") {}
}
This will result in
[error] Caused by: java.lang.UnsupportedOperationException: init of empty list
[error] at scala.collection.immutable.Nil$.init(List.scala:666)
[error] at scala.collection.immutable.Nil$.init(List.scala:661)
[error] at org.typelevel.fix.UnusedIO$$anonfun$checkTree$1.applyOrElse(UnusedIO.scala:90)
[error] at org.typelevel.fix.UnusedIO$$anonfun$checkTree$1.applyOrElse(UnusedIO.scala:84)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:338)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:334)
A simple rule that looks at show"foobar"
strings and warns if there is no variable inside the interpolation.
val foo = "foo"
val a = show"$foo" // Should pass
val b = show"foo" // Should fail
val c = show"${foo}" // Should pass
Hey, I tried adding these Scalafix rules to a project of mine.
I added resolvers += Resolver.sonatypeRepo("snapshots")
into my project/plugins.sbt
but the artifacts cannot be found.
Browsing https://oss.sonatype.org/content/repositories/snapshots/org/typelevel/ does not show any typelevel-scalafix
folders at all.
Have the latest snapshots been expired? :)
Could you maybe publish a 0.1 tag to push a JAR into the release channel?
Thank you :)
Inspired by typelevel/otel4s#14 (comment). This seems hard and I'm not sure if it's actually possible without making some (arguably reasonable) assumptions like nobody wants a List[Unit]
:)
There's already a rule for this in cats itself, intended to help with the 2.2.0 upgrade I believe.
https://github.com/typelevel/cats/blob/3314acd0e921140d939aafffd745a98d55556814/scalafix/rules/src/main/scala/fix/Cats_v2_2_0.scala
But since these instances are not deprecated (I assume that there are Reasons), it is easy to use them in new code by mistake (I just cleaned up a use in one of my projects, which is why I thought we might add this).
I am just running through a few test scenarios :)
Detected:
def test(): IO[Long] = for {
a <- IO.pure(42L)
_ = IO.println("hello")
} yield a
Not detected:
def test(): IO[Long] = for {
a <- IO.pure(42L)
_ = IO { println("hello") }
} yield a
Not detected:
def test(): Long = {
IO { println("hello") }
42
}
So far the rule definitely helps with common cases of "forgotten IO" :)
Just leaving these here as potential test cases for future improvements.
And similar for CE GenConcurrent
etc.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.