Skip to content

Commit

Permalink
support tagChunkSize replacements at arbitrary depths
Browse files Browse the repository at this point in the history
  • Loading branch information
bpholt committed Jan 30, 2024
1 parent e74ff4c commit ad5f0b9
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 4 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ lazy val `scalafix-rules` = (project in file("scalafix/rules"))
crossScalaVersions := V.ScalafixScalaVersions,
libraryDependencies ++= Seq(
"ch.epfl.scala" %% "scalafix-core" % _root_.scalafix.sbt.BuildInfo.scalafixVersion,
"org.typelevel" %% "scalac-compat-annotation" % "0.1.4",
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ rule = com.dwolla.security.crypto.V04to05
*/
import cats.effect.*
import com.dwolla.security.crypto.*
import eu.timepit.refined.auto.*
import org.bouncycastle.openpgp.PGPPublicKey
import org.typelevel.log4cats.LoggerFactory

Expand All @@ -16,13 +17,19 @@ object SeveralDifferentUses {

// all arguments set
alg.encrypt(key, chunkSize, Option("filename"), Encryption.Aes256, Compression.Bzip2, PgpLiteralDataPacketFormat.Utf8)
alg.encrypt(key, tagChunkSize(42), Option("filename"), Encryption.Aes256, Compression.Bzip2, PgpLiteralDataPacketFormat.Utf8)

// all arguments set with named parameters
alg.encrypt(key = key, chunkSize = chunkSize, fileName = Option("filename"), encryption = Encryption.Aes256, compression = Compression.Bzip2, packetFormat = PgpLiteralDataPacketFormat.Utf8)
alg.encrypt(key = key, chunkSize = {
tagChunkSize(42)
}, fileName = Option("filename"), encryption = Encryption.Aes256, compression = Compression.Bzip2, packetFormat = PgpLiteralDataPacketFormat.Utf8)
alg.encrypt(key, chunkSize = chunkSize, fileName = Option("filename"), encryption = Encryption.Aes256, compression = Compression.Bzip2, packetFormat = PgpLiteralDataPacketFormat.Utf8)

// random assortments
alg.encrypt(key, chunkSize, Option("filename"))
alg.encrypt(key, {
tagChunkSize(42)
}, Option("filename"))
alg.encrypt(key, fileName = Option("filename"), chunkSize = chunkSize)
alg.encrypt(key = key, encryption = Encryption.Aes256, packetFormat = PgpLiteralDataPacketFormat.Utf8)
alg.encrypt(key, fileName = Option("filename"), compression = Compression.Bzip2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package example

import cats.effect.*
import com.dwolla.security.crypto.*
import eu.timepit.refined.auto.*
import org.bouncycastle.openpgp.PGPPublicKey
import org.typelevel.log4cats.LoggerFactory

Expand All @@ -14,13 +15,19 @@ object SeveralDifferentUses {

// all arguments set
alg.encrypt(EncryptionConfig().withChunkSize(chunkSize).withFileName(Option("filename")).withEncryption(Encryption.Aes256).withCompression(Compression.Bzip2).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)
alg.encrypt(EncryptionConfig().withChunkSize(ChunkSize(42)).withFileName(Option("filename")).withEncryption(Encryption.Aes256).withCompression(Compression.Bzip2).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)

// all arguments set with named parameters
alg.encrypt(EncryptionConfig().withChunkSize(chunkSize).withFileName(Option("filename")).withEncryption(Encryption.Aes256).withCompression(Compression.Bzip2).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)
alg.encrypt(EncryptionConfig().withChunkSize({
ChunkSize(42)
}).withFileName(Option("filename")).withEncryption(Encryption.Aes256).withCompression(Compression.Bzip2).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)
alg.encrypt(EncryptionConfig().withChunkSize(chunkSize).withFileName(Option("filename")).withEncryption(Encryption.Aes256).withCompression(Compression.Bzip2).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)

// random assortments
alg.encrypt(EncryptionConfig().withChunkSize(chunkSize).withFileName(Option("filename")), key)
alg.encrypt(EncryptionConfig().withChunkSize({
ChunkSize(42)
}).withFileName(Option("filename")), key)
alg.encrypt(EncryptionConfig().withFileName(Option("filename")).withChunkSize(chunkSize), key)
alg.encrypt(EncryptionConfig().withEncryption(Encryption.Aes256).withPacketFormat(PgpLiteralDataPacketFormat.Utf8), key)
alg.encrypt(EncryptionConfig().withFileName(Option("filename")).withCompression(Compression.Bzip2), key)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dwolla.security.crypto

import scalafix.v1.*
import org.typelevel.scalaccompat.annotation.*

import scala.annotation.tailrec
import scala.meta.*
Expand Down Expand Up @@ -50,6 +51,7 @@ class V04to05 extends SemanticRule("com.dwolla.security.crypto.V04to05") {
val parameterName = parameter.displayName

s :+ (parameterName.capitalize -> value)
case _ => throw new RuntimeException(s"Unexpected method signature ${info.signature} (how did the code being modified ever compile?)")
}
case _ => s
}
Expand All @@ -58,11 +60,39 @@ class V04to05 extends SemanticRule("com.dwolla.security.crypto.V04to05") {

Patch.replaceTree(t, sortKeyToEnd(map).foldLeft(s"(EncryptionConfig()") {
case (s, ("key", term)) => s + s", $term)"
case (s, (argName, Term.Apply.After_4_6_0(Term.Name("tagChunkSize"), Term.ArgClause(List(term), _)))) => s + s".with$argName(ChunkSize($term))"
case (s, (argName, term)) => s + s".with$argName($term)"
case (s, (argName, term)) =>
tagChunkSizeTermReplacement(term)
.map(updatedChunkSize => s + s".with$argName($updatedChunkSize)")
.getOrElse(s + s".with$argName($term)")
})
}

@nowarn213("msg=method newBuilder in object StringBuilder is deprecated.*")
private def tagChunkSizeTermReplacement(term: Term): Option[String] = {
val chunkSizeTerms = term.collect {
case t@Term.Apply.After_4_6_0(Term.Name("tagChunkSize"), Term.ArgClause(List(_), _)) => t.pos
}

val updatedChunkSize =
chunkSizeTerms
.foldLeft(StringBuilder.newBuilder) { case (acc, t) =>
val tokens = term.tokens.toString()

val replacementLength = "tagChunkSize".length
val start = t.start - term.pos.start + replacementLength
val end = tokens.length

acc
.append(tokens.slice(0, t.start - term.pos.start).mkString)
.append("ChunkSize")
.append(tokens.slice(start, end).mkString)
}
.toString()

if (chunkSizeTerms.isEmpty) None
else Some(updatedChunkSize)
}

private def sortKeyToEnd(terms: List[(String, Term)]): List[(String, Term)] = {
val key = terms.toMap.apply("key")

Expand Down

0 comments on commit ad5f0b9

Please sign in to comment.