From 2bd80fe5e86eb73e68de7d21e9e5d3becc7bf34d Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Thu, 1 Feb 2024 18:39:26 -0600 Subject: [PATCH] add documentation for the Scalafixes --- README.md | 47 ++++++++++++++++--- .../com/dwolla/security/crypto/V04to05.scala | 16 +++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 77d63f6b..d203f3a5 100644 --- a/README.md +++ b/README.md @@ -7,28 +7,32 @@ A library for encrypting and decrypting fs2 `Stream[F, Byte]` using PGP. Artifact Description -Cats Effect Version -fs2 Version Scala 2.12 Scala 2.13 +Scala 3 "fs2-pgp" Load PGP keys and use them to encrypt, decrypt, and armor byte streams. -Cats Effect 3 -fs2 3.x + "pgp-testkit" ScalaCheck Generators and Arbitrary instances for PGP classes -Cats Effect 3 -fs2 3.x + + + +"fs2-pgp-scalafix" +Scalafix rewrite rules to help update from `v0.4` to `v0.5` + + + @@ -124,3 +128,34 @@ hQEMAzY5h81qQKpXAQf/YTq6GtTkWlbg2DRu7r133FZaAudA149WB2BV/vsgyHkN ## Decryption Read a `PGPPrivateKey` using `PGPKeyAlg[F]`, then pipe the encrypted message bytes through `CryptoAlg[F].decrypt`. + +## Scalafix Rule + +Add Scalafix to your project's build by [following the instructions](https://scalacenter.github.io/scalafix/docs/users/installation.html#sbt): + +1. Add the Scalafix plugin to the project by adding this to `project/plugins.sbt`: + + ```scala + addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.11.1") + ``` + +2. Enable SemanticDB by adding this to `build.sbt`: + + ```scala + ThisBuild / semanticdbEnabled := true + ThisBuild / semanticdbVersion := scalafixSemanticdb.revision + ThisBuild / scalafixScalaBinaryVersion := CrossVersion.binaryScalaVersion(scalaVersion.value) + ThisBuild / scalafixDependencies += "com.dwolla" %% "fs2-pgp-scalafix" % "0.5.0" + ``` + +3. Make sure everything compiles, and run the Scalafix rule on the sbt console: + + ``` + Test/compile + Test/scalafix com.dwolla.security.crypto.V04to05 + scalafix com.dwolla.security.crypto.V04to05 + ``` + + (Run the Scalafix rule on the leafs of your project graph, and then work back to the middle. Tests should be updated before production code, because if the production code is updated, the test project won't compile anymore, etc.) + +4. Update the fs2-pgp version from `v0.4` to `v0.5`. (At this point, you can remove the Scalafix and SemanticDB keys from your build if you want.) diff --git a/scalafix/rules/src/main/scala/com/dwolla/security/crypto/V04to05.scala b/scalafix/rules/src/main/scala/com/dwolla/security/crypto/V04to05.scala index 66a2aa78..45fcf269 100644 --- a/scalafix/rules/src/main/scala/com/dwolla/security/crypto/V04to05.scala +++ b/scalafix/rules/src/main/scala/com/dwolla/security/crypto/V04to05.scala @@ -10,10 +10,22 @@ class V04to05 extends SemanticRule("com.dwolla.security.crypto.V04to05") { override def fix(implicit doc: SemanticDocument): Patch = doc.tree.collect { + /* + * `Crypto[F]` -> `Crypto.resource[F]` + */ case t@Term.ApplyType.After_4_6_0(Term.Name("CryptoAlg"), Type.ArgClause(List(Type.Name(name)))) if t.symbol.normalized.value == "com.dwolla.security.crypto.CryptoAlg." => Patch.replaceTree(t, s"CryptoAlg.resource[$name]").atomic + + /* + * `cryptoAlg.armor()` -> `cryptoAlg.armor` + */ case t@Term.Apply.After_4_6_0(Term.Select(Term.Name(name), Term.Name("armor")), Term.ArgClause(List(), None)) if t.symbol.normalized.value == "com.dwolla.security.crypto.CryptoAlg.armor." => Patch.replaceTree(t, s"$name.armor").atomic + + /* + * Rewrite the various named and optional parameters of the `encrypt` method to use + * the `EncryptionConfig` object. + */ case t@Term.Apply.After_4_6_0(Term.Select(Term.Name(_), fun@Term.Name("encrypt")), argClause@Term.ArgClause(_, _)) if t.symbol.normalized.value == "com.dwolla.security.crypto.CryptoAlg.encrypt." => try { argClause match { @@ -28,6 +40,10 @@ class V04to05 extends SemanticRule("com.dwolla.security.crypto.V04to05") { case ex: NoSuchElementException if ex.getMessage == "key not found: key" => throw pathedException(fun)(s => new RuntimeException(s"Key not found at $s")) } + + /* + * `tagChunkSize(foo)` -> `ChunkSize(foo)` + */ case t@Term.Apply.After_4_6_0(Term.Name("tagChunkSize"), _) if !isEncryptAParent(t) && t.symbol.normalized.value == "com.dwolla.security.crypto.package.tagChunkSize." => Patch.replaceToken(t.tokens.head, "ChunkSize") }.asPatch